diff options
author | Paul Webster | 2013-02-14 17:36:43 +0000 |
---|---|---|
committer | Thomas Watson | 2013-02-15 15:50:06 +0000 |
commit | b22f25b711d260fe88c83d320dde89a9f56db7d6 (patch) | |
tree | a890c0b561c899cd47e5e78c433aed5e3d4c8be7 /features/org.eclipse.equinox.executable.feature/library | |
parent | cb70c695f5c85be396bcb024db894795f8ec3262 (diff) | |
download | rt.equinox.framework-b22f25b711d260fe88c83d320dde89a9f56db7d6.tar.gz rt.equinox.framework-b22f25b711d260fe88c83d320dde89a9f56db7d6.tar.xz rt.equinox.framework-b22f25b711d260fe88c83d320dde89a9f56db7d6.zip |
Bug 394216 - o.e.equinox.executables IUs must be in build repo
Generate the correct feature and a secondary IU that doesn't
include all executables.
Diffstat (limited to 'features/org.eclipse.equinox.executable.feature/library')
86 files changed, 14431 insertions, 0 deletions
diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/.cvsignore b/features/org.eclipse.equinox.executable.feature/library/carbon/.cvsignore new file mode 100644 index 000000000..f0fdae47c --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/.cvsignore @@ -0,0 +1,3 @@ +*.o +eclipse +*.so diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/build.sh b/features/org.eclipse.equinox.executable.feature/library/carbon/build.sh new file mode 100644 index 000000000..ac923d2ff --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/build.sh @@ -0,0 +1,100 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2000, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +# +# Usage: sh build.sh [<optional switches>] [clean] +# +# where the optional switches are: +# -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +# -os <DEFAULT_OS> - default Eclipse "-os" value +# -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value +# -ws <DEFAULT_WS> - default Eclipse "-ws" value +# +# +# This script can also be invoked with the "clean" argument. + +cd `dirname $0` + +# Define default values for environment variables used in the makefiles. +programOutput="eclipse" +defaultOS="macosx" +defaultOSArch="x86" +defaultWS="carbon" +makefile="make_carbon.mak" +if [ "$OS" = "" ]; then + OS=`uname -s` +fi + +# Parse the command line arguments and override the default values. +extraArgs="" +while [ "$1" != "" ]; do + if [ "$1" = "-os" ] && [ "$2" != "" ]; then + defaultOS="$2" + shift + elif [ "$1" = "-arch" ] && [ "$2" != "" ]; then + defaultOSArch="$2" + shift + elif [ "$1" = "-ws" ] && [ "$2" != "" ]; then + defaultWS="$2" + shift + elif [ "$1" = "-output" ] && [ "$2" != "" ]; then + programOutput="$2" + shift + else + extraArgs="$extraArgs $1" + fi + shift +done + +# Set up environment variables needed by the makefiles. +PROGRAM_OUTPUT="$programOutput" +DEFAULT_OS="$defaultOS" +DEFAULT_OS_ARCH="$defaultOSArch" +DEFAULT_WS="$defaultWS" +EXEC_DIR=../../../../../rt.equinox.binaries/org.eclipse.equinox.executable +PPC_OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/ppc/Eclipse.app/Contents/MacOS" +X86_OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/x86/Eclipse.app/Contents/MacOS" +X86_64_OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/x86_64/Eclipse.app/Contents/MacOS" + +if [ "$DEFAULT_WS" == "cocoa" ]; then + makefile="make_cocoa.mak" + export MACOSX_DEPLOYMENT_TARGET=10.5 +else + export MACOSX_DEPLOYMENT_TARGET=10.3 +fi + +if [ "$DEFAULT_OS_ARCH" == "x86_64" ]; then + echo "build x86_64" + ARCHS="-arch x86_64" + PROGRAM_OUTPUT_DIR=$X86_64_OUTPUT_DIR + DEFAULT_OS_ARCH="x86_64" +else + echo "build x86 and ppc" + ARCHS="-arch i386 -arch ppc" + PROGRAM_OUTPUT_DIR=$X86_OUTPUT_DIR +fi + +export PPC_OUTPUT_DIR X86_OUTPUT_DIR X86_64_OUTPUT_DIR PROGRAM_OUTPUT DEFAULT_OS DEFAULT_OS_ARCH DEFAULT_WS ARCHS PROGRAM_OUTPUT_DIR + +# If the OS is supported (a makefile exists) +if [ "$makefile" != "" ]; then + if [ "$extraArgs" != "" ]; then + make -f $makefile $extraArgs + else + echo "Building $OS launcher. Defaults: -os $DEFAULT_OS -arch $DEFAULT_OS_ARCH -ws $DEFAULT_WS" + make -f $makefile clean + make -f $makefile all + make -f $makefile install + fi +else + echo "Unknown OS ($OS) -- build aborted" +fi diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/build.xml b/features/org.eclipse.equinox.executable.feature/library/carbon/build.xml new file mode 100644 index 000000000..990298e64 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/build.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="install"/> + </exec> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbon.c b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbon.c new file mode 100644 index 000000000..29348fc56 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbon.c @@ -0,0 +1,855 @@ +/* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andre Weinand (OTI Labs) + * David Green - OpenJDK bsd port integration + */ + +/* MacOS X Carbon specific logic for displaying the splash screen. */ + +#include "eclipseOS.h" +#include "eclipseCommon.h" +#include "eclipseJNI.h" +#include "eclipseUtil.h" + +#include <unistd.h> +#include <sys/stat.h> +#include <CoreServices/CoreServices.h> +#ifdef COCOA +#include <Cocoa/Cocoa.h> +#else +#include <Carbon/Carbon.h> +#include "NgCommon.h" +#include "NgImageData.h" +#include "NgWinBMPFileFormat.h" +#endif +#include <mach-o/dyld.h> +#include <pthread.h> + +#define startupJarName "startup.jar" +#define LAUNCHER "-launcher" +#define SPLASH_LAUNCHER "/Resources/Splash.app/Contents/" + +#define DEBUG 0 + +static _TCHAR* noForkingMsg = _T_ECLIPSE("Internal Error, forking the jvm is not supported on MacOS.\n"); + +char *findCommand(char *command); + +/* Global Variables */ +char* defaultVM = "java"; +char* vmLibrary = "JavaVM"; +char* shippedVMDir = "../../../jre/Contents/Home/jre/bin/"; +int isSUN = 0; + +static void adjustLibraryPath(char * vmLibrary); +static char * findLib(char * command); + +#ifdef i386 +#define JAVA_ARCH "i386" +#define JAVA_HOME_ARCH "i386" +#elif defined(__ppc__) || defined(__powerpc64__) +#define JAVA_ARCH "ppc" +#define JAVA_HOME_ARCH "ppc" +#elif defined(__amd64__) || defined(__x86_64__) +#define JAVA_ARCH "amd64" +#define JAVA_HOME_ARCH "x86_64" +#else +#define JAVA_ARCH DEFAULT_OS_ARCH +#define JAVA_HOME_ARCH DEFAULT_OS_ARCH +#endif + +#define LIB_PATH_VAR _T_ECLIPSE("LD_LIBRARY_PATH") +#define DYLD_FALLBACK_VAR _T_ECLIPSE("DYLD_FALLBACK_LIBRARY_PATH") + +#define MAX_LOCATION_LENGTH 40 /* none of the jvmLocations strings should be longer than this */ +#define MAX_JVMLIB_LENGTH 15 /* none of the jvmLibs strings should be longer than this */ +static const char* jvmLocations[] = { "../lib/" JAVA_ARCH "/client", + "../lib/" JAVA_ARCH "/server", + "../jre/lib/" JAVA_ARCH "/client", + "../jre/lib/" JAVA_ARCH "/server", + "../jre/lib/client", + "../jre/lib/server", NULL }; +static const char* jvmLibs[] = { "libjvm.dylib", "libjvm.jnilib", "libjvm.so", NULL }; + +/* Define the window system arguments for the various Java VMs. */ +static char* argVM_JAVA[] = { "-XstartOnFirstThread", NULL }; + +/* thread stuff */ +typedef struct { + _TCHAR * libPath; + _TCHAR ** vmArgs; + _TCHAR ** progArgs; + _TCHAR * jarFile; + JavaResults* result; +} StartVMArgs; + +#ifdef COCOA +static NSWindow* window = nil; +@interface KeyWindow : NSWindow { } +- (BOOL)canBecomeKeyWindow; +@end + +@implementation KeyWindow +- (BOOL)canBecomeKeyWindow { + return YES; +} + +- (void)close { + [super close]; + window = nil; +} + +@end + +@interface AppleEventDelegate : NSObject +- (void)handleOpenDocuments:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +@end +@implementation AppleEventDelegate + NSTimer *timer; + NSMutableArray *files; + +- (void)handleOpenDocuments:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + int count = [event numberOfItems]; + int index = 1; + + if (!files) { + files = [NSMutableArray arrayWithCapacity:count]; + [files retain]; + } + + for (index = 1; index<=count; index++) { + CFURLRef url = NULL; + NSAppleEventDescriptor *desc = [event descriptorAtIndex:index], *coerceDesc; + if (!desc) continue; + if ((coerceDesc = [desc coerceToDescriptorType: typeFSRef]) != NULL) { + url = CFURLCreateFromFSRef(kCFAllocatorDefault, [[coerceDesc data] bytes]); + } else if ((coerceDesc = [desc coerceToDescriptorType: typeFileURL]) != NULL) { + NSData *data = [coerceDesc data]; + url = CFURLCreateWithBytes(kCFAllocatorDefault, [data bytes], [data length], kCFStringEncodingUTF8, NULL); + } + if (url) { + NSString *pathName = (NSString *)CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + [files addObject:pathName]; + [pathName release]; + CFRelease(url); + } + } + + if (!timer) { + timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 + target: self + selector: @selector(handleTimer:) + userInfo: nil + repeats: YES]; + } + [pool release]; +} +- (void) handleTimer: (NSTimer *) timer { + NSObject *delegate = [[NSApplication sharedApplication] delegate]; + if (delegate != NULL && [delegate respondsToSelector: @selector(application:openFiles:)]) { + [delegate performSelector:@selector(application:openFiles:) withObject:[NSApplication sharedApplication] withObject:files]; + [files release]; + [timer invalidate]; + } +} +@end +#endif + +static CFRunLoopRef loopRef = NULL; +static void * startThread(void * init); +static void runEventLoop(CFRunLoopRef ref); +static void dummyCallback(void * info) {} +#ifndef COCOA +static CFMutableArrayRef files; +static EventHandlerRef appHandler; +static int SWT_CLASS = 'SWT-'; +static int SWT_OPEN_FILE_KIND = 1; +static int SWT_OPEN_FILE_PARAM = 'odoc'; +#endif + +int main() { + return -1; +} + +void installAppleEventHandler(); + +int reuseWorkbench(_TCHAR** filePath, int timeout) { + installAppleEventHandler(); + return 0; +} + +#ifdef COCOA + +/* Show the Splash Window + * + * Create the splash window, load the bitmap and display the splash window. + */ +int showSplash( const _TCHAR* featureImage ) +{ + if (window != NULL) + return 0; /*already showing */ + if (featureImage == NULL) + return ENOENT; + + int result = ENOENT; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [NSApplication sharedApplication]; + NSImage* image = [[NSImage alloc] initByReferencingFile: [NSString stringWithUTF8String: featureImage]]; + if (image != NULL) { + NSImageRep* imageRep = [image bestRepresentationForDevice: [[NSScreen mainScreen] deviceDescription]]; + NSRect rect = {{0, 0}, {[imageRep pixelsWide], [imageRep pixelsHigh]}}; + [image setSize: NSMakeSize([imageRep pixelsWide], [imageRep pixelsHigh])]; + [image autorelease]; + window = [[KeyWindow alloc] initWithContentRect: rect styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: 0]; + if (window != nil) { + [window center]; + [window setBackgroundColor: [NSColor colorWithPatternImage: image]]; + [window makeKeyAndOrderFront: nil]; + dispatchMessages(); + result = 0; + } + } + [pool release]; + return result; +} + +void takeDownSplash() { + if (window != 0) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [window close]; + window = nil; + [pool release]; + } +} + +void dispatchMessages() { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSEvent* event; + NSApplication* application = [NSApplication sharedApplication]; + while ((event = [application nextEventMatchingMask: 0 untilDate: nil inMode: NSDefaultRunLoopMode dequeue: TRUE]) != nil) { + [application sendEvent: event]; + } + [pool release]; +} + +#else +static WindowRef window; +static ControlRef pane = NULL; +static CGImageRef image = NULL; +static CGImageRef loadBMPImage(const char *image); + +typedef CGImageSourceRef (*CGImageSourceCreateWithURL_FUNC) (CFURLRef, CFDictionaryRef); +typedef CGImageRef (*CGImageSourceCreateImageAtIndex_FUNC)(CGImageSourceRef, size_t, CFDictionaryRef); +static CGImageSourceCreateWithURL_FUNC createWithURL = NULL; +static CGImageSourceCreateImageAtIndex_FUNC createAtIndex = NULL; + +static pascal OSErr openDocumentsProc(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon); + +static OSStatus drawProc (EventHandlerCallRef eventHandlerCallRef, EventRef eventRef, void * data) { + int result = CallNextEventHandler(eventHandlerCallRef, eventRef); + if (image) { + ControlRef control; + CGContextRef context; + + GetEventParameter(eventRef, kEventParamDirectObject, typeControlRef, NULL, 4, NULL, &control); + GetEventParameter(eventRef, kEventParamCGContextRef, typeCGContextRef, NULL, 4, NULL, &context); + + HIRect rect; + HIViewGetBounds(control, &rect); + HIViewDrawCGImage(context, &rect, image); + } + return result; +} + +static OSStatus disposeProc (EventHandlerCallRef eventHandlerCallRef, EventRef eventRef, void * data) { + window = NULL; + return eventNotHandledErr; +} + +void loadImageFns() +{ + static int initialized = 0; + static CFBundleRef bundle = NULL; + + if (!initialized) { + if (!bundle) bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon")); + if (bundle) createAtIndex = (CGImageSourceCreateImageAtIndex_FUNC)CFBundleGetFunctionPointerForName(bundle, CFSTR("CGImageSourceCreateImageAtIndex")); + if (bundle) createWithURL = (CGImageSourceCreateWithURL_FUNC)CFBundleGetFunctionPointerForName(bundle, CFSTR("CGImageSourceCreateWithURL")); + initialized = 1; + } +} + +static OSStatus appleEventProc(EventHandlerCallRef inCaller, EventRef theEvent, void* inRefcon) { + EventRecord eventRecord; + Boolean release = false; + EventQueueRef queue; + + queue = GetCurrentEventQueue(); + if (IsEventInQueue (queue, theEvent)) { + RetainEvent (theEvent); + release = true; + RemoveEventFromQueue (queue, theEvent); + } + ConvertEventRefToEventRecord (theEvent, &eventRecord); + AEProcessAppleEvent (&eventRecord); + if (release) ReleaseEvent (theEvent); + return noErr; +} + +static void timerProc(EventLoopTimerRef timer, void *userData) { + EventTargetRef target = GetApplicationEventTarget(); + CFIndex count = CFArrayGetCount (files); + int i; + for (i=0; i<count; i++) { + CFStringRef file = (CFStringRef) CFArrayGetValueAtIndex(files, i); + EventRef event = NULL; + CreateEvent (NULL, SWT_CLASS, SWT_OPEN_FILE_KIND, 0, kEventAttributeNone, &event); + SetEventParameter (event, SWT_OPEN_FILE_PARAM, typeCFStringRef, sizeof(file), &file); + OSStatus status = SendEventToEventTarget(event, target); + ReleaseEvent(event); + if (status == eventNotHandledErr) return; + } + CFRelease(files); + RemoveEventLoopTimer(timer); + RemoveEventHandler(appHandler); + AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(openDocumentsProc), false); +} + +static pascal OSErr openDocumentsProc(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon) { + AEDescList docList; + FSRef theFSRef; + long index; + long count = 0; + + AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList); + AECountItems(&docList, &count); + for(index = 1; index <= count; index++) { + AEGetNthPtr(&docList, index, typeFSRef, NULL, NULL, &theFSRef, sizeof(FSRef), NULL); + CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorDefault, &theFSRef); + CFStringRef pathName = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + if (!files) { + files = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); + InstallEventLoopTimer(GetMainEventLoop(), 1, 1, NewEventLoopTimerUPP(timerProc), NULL, NULL); + } + CFArrayAppendValue(files, pathName); + CFRelease(pathName); + CFRelease(url); + } + AEDisposeDesc(&docList); + return noErr; +} + +/* Show the Splash Window + * + * Create the splash window, load the bitmap and display the splash window. + */ +int showSplash( const _TCHAR* featureImage ) +{ + Rect wRect; + int w, h, deviceWidth, deviceHeight; + int attributes; + EventTypeSpec draw = {kEventClassControl, kEventControlDraw}; + EventTypeSpec dispose = {kEventClassWindow, kEventWindowDispose}; + ControlRef root; + + if(window != NULL) + return 0; /*already showing */ + if (featureImage == NULL) + return ENOENT; + + loadImageFns(); + if (createWithURL && createAtIndex) { + CFStringRef imageString = CFStringCreateWithCString(kCFAllocatorDefault, featureImage, kCFStringEncodingUTF8); + if(imageString != NULL) { + CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, imageString, kCFURLPOSIXPathStyle, false); + if(url != NULL) { + CGImageSourceRef imageSource = createWithURL(url, NULL); + if(imageSource != NULL) { + image = createAtIndex(imageSource, 0, NULL); + } + CFRelease(url); + } + } + CFRelease(imageString); + } else { + image = loadBMPImage(featureImage); + } + + /*If the splash image data could not be loaded, return an error.*/ + if (image == NULL) + return ENOENT; + + w = CGImageGetWidth(image); + h = CGImageGetHeight(image); + + GetAvailableWindowPositioningBounds(GetMainDevice(), &wRect); + + deviceWidth= wRect.right - wRect.left; + deviceHeight= wRect.bottom - wRect.top; + + wRect.left+= (deviceWidth-w)/2; + wRect.top+= (deviceHeight-h)/3; + wRect.right= wRect.left + w; + wRect.bottom= wRect.top + h; + + attributes = kWindowStandardHandlerAttribute | kWindowCompositingAttribute; + attributes &= GetAvailableWindowAttributes(kSheetWindowClass); + CreateNewWindow(kSheetWindowClass, attributes, &wRect, &window); + if (window != NULL) { + GetRootControl(window, &root); + wRect.left = wRect.top = 0; + wRect.right = w; + wRect.bottom = h; + CreateUserPaneControl(window, &wRect, kControlSupportsEmbedding | kControlSupportsFocus | kControlGetsFocusOnClick, &pane); + HIViewAddSubview(root, pane); + + InstallEventHandler(GetControlEventTarget(pane), (EventHandlerUPP)drawProc, 1, &draw, NULL, NULL); + InstallEventHandler(GetWindowEventTarget(window), (EventHandlerUPP)disposeProc, 1, &dispose, NULL, NULL); + ShowWindow(window); + dispatchMessages(); + } + + return 0; +} + +void takeDownSplash() { + if( window != 0) { + DisposeWindow(window); + window = NULL; + } + if(image){ + CGImageRelease(image); + image = NULL; + } +} + +void dispatchMessages() { + EventRef event; + EventTargetRef target; + + target = GetEventDispatcherTarget(); + while( ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &event) == noErr ) { + SendEventToEventTarget(event, target); + ReleaseEvent(event); + } +} +#endif + +void installAppleEventHandler() { +#ifdef COCOA + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + AppleEventDelegate *appleEventDelegate = [[AppleEventDelegate alloc] init]; + [NSApplication sharedApplication]; + NSAppleEventManager *manager = [NSAppleEventManager sharedAppleEventManager]; + [manager setEventHandler:appleEventDelegate + andSelector:@selector(handleOpenDocuments:withReplyEvent:) + forEventClass:kCoreEventClass + andEventID:kAEOpenDocuments]; +// [appleEventDelegate release]; + [pool release]; +#else + EventTypeSpec kEvents[] = { {kEventClassAppleEvent, kEventAppleEvent} }; + InstallApplicationEventHandler(NewEventHandlerUPP(appleEventProc), GetEventTypeCount(kEvents), kEvents, 0, &appHandler); + AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(openDocumentsProc), 0, false); +#endif +} + +jlong getSplashHandle() { + return (jlong)window; +} + +/* Get the window system specific VM arguments */ +char** getArgVM( char* vm ) +{ + char** result; + + /* Use the default arguments for a standard Java VM */ + result = argVM_JAVA; + + return result; +} + +char * getJavaHome() { + FILE *fp; + char path[4096]; + char *result, *start; + sprintf(path, "/usr/libexec/java_home -a %s", JAVA_HOME_ARCH); + fp = popen(path, "r"); + if (fp == NULL) { + return NULL; + } + while (fgets(path, sizeof(path)-1, fp) != NULL) { + } + result = path; + start = strchr(result, '\n'); + if (start) { + start[0] = 0; + } + sprintf(path, "%s/bin/java", result); + pclose(fp); + return strdup(path); +} + +char * findVMLibrary( char* command ) { + char *start, *end; + char *version, *result, *cmd; + int length; + + /*check first to see if command already points to the library */ + if (strcmp(command, JAVA_FRAMEWORK) == 0) { + return JAVA_FRAMEWORK; + } + + /* select a version to use based on the command */ + start = strstr(command, "/Versions/"); + if (start != NULL){ + start += 10; + end = strchr( start, dirSeparator); + if (end != NULL && end > start) { + length = end - start; + version = malloc(length + 1); + strncpy(version, start, length); + version[length] = 0; + + /*only set a version if it starts with a number */ + if(strtol(version, NULL, 10) != 0 || version[0] == '0') { + setenv("JAVA_JVM_VERSION", version, 1); + } + + free(version); + } + } + cmd = command; + if (strstr(cmd, "/JavaVM.framework/") != NULL && (strstr(cmd, "/Current/") != NULL || strstr(cmd, "/A/") != NULL)) { + cmd = getJavaHome(); + } + result = JAVA_FRAMEWORK; + if (strstr(cmd, "/JavaVM.framework/") == NULL) { + char * lib = findLib(cmd); + if (lib != NULL) { + adjustLibraryPath(lib); + result = lib; + } + } + if (cmd != command) free(cmd); + return result; +} + +static char * findLib(char * command) { + int i, q; + int pathLength; + struct stat stats; + char * path; /* path to resulting jvm shared library */ + char * location; /* points to begining of jvmLocations section of path */ + + if (command != NULL) { + /*check first to see if command already points to the library */ + if (isVMLibrary(command)) { + if (stat(command, &stats) == 0 && (stats.st_mode & S_IFREG) != 0) { /* found it */ + return strdup(command); + } + return NULL; + } + + location = strrchr(command, dirSeparator) + 1; + pathLength = location - command; + path = malloc((pathLength + MAX_LOCATION_LENGTH + 1 + MAX_JVMLIB_LENGTH + 1) * sizeof(char)); + strncpy(path, command, pathLength); + location = &path[pathLength]; + + /* + * We are trying base/jvmLocations[*]/vmLibrary + * where base is the directory containing the given java command, normally jre/bin + */ + for (q = 0; jvmLibs[q] != NULL; ++q) { + const char *jvmLib = jvmLibs[q]; + i = -1; + while (jvmLocations[++i] != NULL) { + sprintf(location, "%s%c%s", jvmLocations[i], dirSeparator, jvmLib); + /*fprintf(stderr,"checking path: %s\n",path);*/ + if (stat(path, &stats) == 0 && (stats.st_mode & S_IFREG) != 0) + { /* found it */ + return path; + } + } + } + } + return NULL; +} + +/* adjust the LD_LIBRARY_PATH for the vmLibrary */ +static void adjustLibraryPath(char * vmLibrary) { + char * c; + char * ldPath, *dylibPath; + char * newPath; + int i; + int numPaths = 0; + int length = 0; + int needAdjust = 0, needDylibAdjust = 0; + + char ** paths = getVMLibrarySearchPath(vmLibrary); + + ldPath = (char*) getenv(LIB_PATH_VAR); + if (!ldPath) { + ldPath = _T_ECLIPSE(""); + needAdjust = 1; + } else { + needAdjust = !containsPaths(ldPath, paths); + } + + dylibPath = (char*) getenv(DYLD_FALLBACK_VAR); + if (!dylibPath) { + dylibPath = _T_ECLIPSE(""); + needDylibAdjust = 1; + } else { + needDylibAdjust = !containsPaths(dylibPath, paths); + } + + if (!needAdjust && !needDylibAdjust) { + for (i = 0; paths[i] != NULL; i++) + free(paths[i]); + free(paths); + return; + } + + c = concatStrings(paths); + + /* set the value for LD_LIBRARY_PATH */ + length = strlen(ldPath); + newPath = malloc((_tcslen(c) + length + 1) * sizeof(_TCHAR)); + _stprintf(newPath, _T_ECLIPSE("%s%s"), c, ldPath); + setenv(LIB_PATH_VAR, newPath, 1); + free(newPath); + + /* set the value for DYLD_FALLBACK_LIBRARY_PATH */ + length = strlen(dylibPath); + newPath = malloc((_tcslen(c) + length + 1) * sizeof(_TCHAR)); + _stprintf(newPath, _T_ECLIPSE("%s%s"), c, dylibPath); + setenv(DYLD_FALLBACK_VAR, newPath, 1); + free(newPath); + free(c); + + for (i = 0; i < numPaths; i++) + free(paths[i]); + free(paths); + + /* now we must restart for this to take affect*/ + restartLauncher(initialArgv[0], initialArgv); +} + +void restartLauncher(char* program, char* args[]) { + pid_t pid= fork(); + if (pid == 0) { + /* Child process ... start the JVM */ + execv(program != NULL ? program : args[0], args); + + /* The JVM would not start ... return error code to parent process. */ + _exit(errno); + } else { + exit(0); + } +} + +JavaResults* launchJavaVM( _TCHAR* args[] ) +{ + /*for now always do JNI on Mac, should not come in here */ + JavaResults * results = malloc(sizeof(JavaResults)); + results->launchResult = -1; + results->runResult = 0; + results->errorMessage = _tcsdup(noForkingMsg); + return results; +} + +JavaResults* startJavaVM( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ) +{ + if (secondThread == 0) { + /* Set an environment variable that tells the AWT (if started) we started the JVM on the main thread. */ + char firstThreadEnvVariable[80]; + sprintf(firstThreadEnvVariable, "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid()); + setenv(firstThreadEnvVariable, "1", 1); + return startJavaJNI(libPath, vmArgs, progArgs, jarFile); + } + + /* else, --launcher.secondThread was specified, create a new thread and run the + * vm on it. This main thread will run the CFRunLoop + */ + pthread_t thread; + struct rlimit limit = {0, 0}; + int stackSize = 0; + if (getrlimit(RLIMIT_STACK, &limit) == 0) { + if (limit.rlim_cur != 0) { + stackSize = limit.rlim_cur; + } + } + + /* initialize thread attributes */ + pthread_attr_t attributes; + pthread_attr_init(&attributes); + pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); + if (stackSize != 0) + pthread_attr_setstacksize(&attributes, stackSize); + + /* arguments to start the vm */ + StartVMArgs args; + args.libPath = libPath; + args.vmArgs = vmArgs; + args.progArgs = progArgs; + args.jarFile = jarFile; + args.result = 0; + + loopRef = CFRunLoopGetCurrent(); + + /* create the thread */ + pthread_create( &thread, &attributes, &startThread, &args); + pthread_attr_destroy(&attributes); + + runEventLoop(loopRef); + + return args.result; +} + +void * startThread(void * init) { + StartVMArgs *args = (StartVMArgs *) init; + args->result = startJavaJNI(args->libPath, args->vmArgs, args->progArgs, args->jarFile); + return NULL; +} + +void runEventLoop(CFRunLoopRef ref) { + CFRunLoopSourceContext sourceContext = { .version = 0, .info = NULL, .retain = NULL, .release = NULL, + .copyDescription = NULL, .equal = NULL, .hash = NULL, + .schedule = NULL, .cancel = NULL, .perform = &dummyCallback }; + + CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext); + CFRunLoopAddSource(ref, sourceRef, kCFRunLoopCommonModes); + + CFRunLoopRun(); + CFRelease(sourceRef); +} + +#ifndef COCOA +void disposeData(void *info, void *data, size_t size) +{ + DisposePtr(data); +} + +/** + * loadBMPImage + * Create a QuickDraw PixMap representing the given BMP file. + * + * bmpPathname: absolute path and name to the bmp file + * + * returned value: the PixMapHandle newly created if successful. 0 otherwise. + */ +static CGImageRef loadBMPImage (const char *bmpPathname) { + ng_stream_t in; + ng_bitmap_image_t image; + ng_err_t err= ERR_OK; + CGImageRef ref; + UBYTE1* data = NULL; + + NgInit(); + + if (NgStreamInit(&in, (char*) bmpPathname) != ERR_OK) { + NgError(ERR_NG, "Error can't open BMP file"); + return 0; + } + + NgBitmapImageInit(&image); + err= NgBmpDecoderReadImage (&in, &image); + NgStreamClose(&in); + + if (err != ERR_OK) { + NgBitmapImageFree(&image); + return 0; + } + + UBYTE4 srcDepth= NgBitmapImageBitCount(&image); + if (srcDepth != 24) { /* We only support image depth of 24 bits */ + NgBitmapImageFree(&image); + NgError (ERR_NG, "Error unsupported depth - only support 24 bit"); + return 0; + } + + int width= (int)NgBitmapImageWidth(&image); + int height= (int)NgBitmapImageHeight(&image); + int rowBytes= width * 4; + int alphainfo = kCGImageAlphaNoneSkipFirst | (NgIsMSB() ? 0 : kCGBitmapByteOrder32Little); + data = (UBYTE1*)NewPtr(rowBytes * height); + CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, rowBytes * height, (CGDataProviderReleaseDataCallback)disposeData); + + ref = CGImageCreate(width, height, 8, 32, width * 4, CGColorSpaceCreateDeviceRGB(), alphainfo, provider, NULL, 1, 0); + CGDataProviderRelease(provider); + + /* 24 bit source to direct screen destination */ + NgBitmapImageBlitDirectToDirect(NgBitmapImageImageData(&image), NgBitmapImageBytesPerRow(&image), width, height, + data, 32, rowBytes, NgIsMSB(), 0xff0000, 0x00ff00, 0x0000ff); + + NgBitmapImageFree(&image); + + return ref; +} +#endif + +#define DOCK_ICON_PREFIX "-Xdock:icon=" +#define DOCK_NAME_PREFIX "-Xdock:name=" +#define APP_ICON_PATTERN "APP_ICON_%d" +#define APP_NAME_PATTERN "APP_NAME_%d" + +void processVMArgs(char **vmargs[] ) +{ + int i = -1; + int pid = 0, pidLength = 1, temp = 0; + char * name = NULL, *icon = NULL; + char * c; + + if( *vmargs == NULL) + return; + + while( (*vmargs)[++i] != NULL ) { + /*-Xdock:icon -> APP_ICON_<pid>*/ + if(_tcsncmp((*vmargs)[i], DOCK_ICON_PREFIX, _tcslen(DOCK_ICON_PREFIX)) == 0) { + icon = (*vmargs)[i] + _tcslen(DOCK_ICON_PREFIX); + } + /*-Xdock:name -> APP_NAME_<pid>*/ + else if(_tcsncmp((*vmargs)[i], DOCK_NAME_PREFIX, _tcslen(DOCK_NAME_PREFIX)) == 0) { + name = (*vmargs)[i] + _tcslen(DOCK_NAME_PREFIX); + } + if (name != NULL && icon != NULL) + break; + } + + if (name == NULL && icon == NULL) + return; /* don't need to do anything */ + + temp = pid = getpid(); + /* how many digits in pid? */ + while (temp > 9) { + pidLength++; + temp /= 10; + } + + if (name != NULL) { + c = malloc( (_tcslen(APP_NAME_PATTERN) + pidLength + 1) * sizeof(char*)); + _stprintf( c, APP_NAME_PATTERN, pid ); + setenv(c, name, 1); + } + + if (icon != NULL) { + c = malloc( (_tcslen(icon) + _tcslen(APP_ICON_PATTERN) + pidLength + 1) * sizeof(char*)); + _stprintf( c, APP_ICON_PATTERN, pid ); + setenv(c, icon, 1); + } +} + +int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ) { + return isSUN; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonCommon.c b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonCommon.c new file mode 100644 index 000000000..2870c62e8 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonCommon.c @@ -0,0 +1,195 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseCommon.h" +#include "eclipseOS.h" + +#include <locale.h> +#include <dlfcn.h> +#include <unistd.h> +#include <CoreServices/CoreServices.h> +#ifdef COCOA +#include <Cocoa/Cocoa.h> +#else +#include <Carbon/Carbon.h> +#endif +#include <mach-o/dyld.h> + +char dirSeparator = '/'; +char pathSeparator = ':'; + +static CFBundleRef javaVMBundle = NULL; + +int initialized = 0; + +static void init() { + if (!initialized) { + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); + } +#ifdef COCOA + [NSApplication sharedApplication]; +#else + ClearMenuBar(); +#endif + initialized= true; + } +} + + +/* Initialize Window System + * + * Initialize Carbon. + */ +int initWindowSystem( int* pArgc, char* argv[], int showSplash ) +{ + char *homeDir = getProgramDir(); + /*debug("install dir: %s\n", homeDir);*/ + if (homeDir != NULL) + chdir(homeDir); + + if (showSplash) + init(); + + return 0; +} + +/* Display a Message */ +void displayMessage(char *title, char *message) +{ + CFStringRef inError, inDescription= NULL; + + /* try to break the message into a first sentence and the rest */ + char *pos= strstr(message, ". "); + if (pos != NULL) { + char *to, *from, *buffer= calloc(pos-message+2, sizeof(char)); + /* copy and replace line separators with blanks */ + for (to= buffer, from= message; from <= pos; from++, to++) { + char c= *from; + if (c == '\n') c= ' '; + *to= c; + } + inError= CFStringCreateWithCString(kCFAllocatorDefault, buffer, kCFStringEncodingUTF8); + free(buffer); + inDescription= CFStringCreateWithCString(kCFAllocatorDefault, pos+2, kCFStringEncodingUTF8); + } else { + inError= CFStringCreateWithCString(kCFAllocatorDefault, message, kCFStringEncodingUTF8); + } + + init(); + +#ifdef COCOA + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAlert* alert = [NSAlert alertWithMessageText: (NSString*)(inDescription != nil ? inError : nil) defaultButton: nil alternateButton: nil otherButton: nil informativeTextWithFormat: (NSString*)(inDescription != nil ? inDescription : inError)]; + [[alert window] setTitle: [NSString stringWithUTF8String: title]]; + [alert setAlertStyle: NSCriticalAlertStyle]; + [alert runModal]; + [pool release]; +#else + DialogRef outAlert; + OSStatus status= CreateStandardAlert(kAlertStopAlert, inError, inDescription, NULL, &outAlert); + if (status == noErr) { + DialogItemIndex outItemHit; + RunStandardAlert(outAlert, NULL, &outItemHit); + } else { + /*debug("%s: displayMessage: %s\n", title, message);*/ + } +#endif + CFRelease(inError); + if (inDescription != NULL) + CFRelease(inDescription); +} + +static int isLibrary( _TCHAR* vm ){ + _TCHAR *ch = NULL; + if (vm == NULL) return 0; + ch = _tcsrchr( vm, '.' ); + if(ch == NULL) + return 0; + return (_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0); +} + +/* Load the specified shared library + */ +void * loadLibrary( char * library ){ + if (!isLibrary(library)) { + CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)library, strlen(library), true); + javaVMBundle = CFBundleCreate(kCFAllocatorDefault, url); + CFRelease(url); + return (void*) &javaVMBundle; + } else { + void * result= dlopen(library, RTLD_NOW); + if(result == 0) + printf("%s\n",dlerror()); + return result; + } +} + +/* Unload the shared library + */ +void unloadLibrary( void * handle ){ + if (handle == &javaVMBundle) + CFRelease(javaVMBundle); + else + dlclose(handle); +} + +/* Find the given symbol in the shared library + */ +void * findSymbol( void * handle, char * symbol ){ + if(handle == &javaVMBundle) { + CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, symbol, kCFStringEncodingASCII); + void * ptr = CFBundleGetFunctionPointerForName(javaVMBundle, string); + CFRelease(string); + return ptr; + } else + return dlsym(handle, symbol); +} + +char * resolveSymlinks( char * path ) { + char * result = 0; + CFURLRef url, resolved; + CFStringRef string; + FSRef fsRef; + Boolean isFolder, wasAliased; + + if(path == NULL) + return path; + + string = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, string, kCFURLPOSIXPathStyle, false); + CFRelease(string); + if(url == NULL) + return path; + + if(CFURLGetFSRef(url, &fsRef)) { + if( FSResolveAliasFile(&fsRef, true, &isFolder, &wasAliased) == noErr) { + resolved = CFURLCreateFromFSRef(kCFAllocatorDefault, &fsRef); + if(resolved != NULL) { + string = CFURLCopyFileSystemPath(resolved, kCFURLPOSIXPathStyle); + CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8); + char *s = malloc(length); + if (CFStringGetCString(string, s, length, kCFStringEncodingUTF8)) { + result = s; + } else { + free(s); + } + CFRelease(string); + CFRelease(resolved); + } + } + } + CFRelease(url); + return result; +}
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonMain.c b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonMain.c new file mode 100644 index 000000000..51cafc275 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseCarbonMain.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + */ + +#include "eclipseCommon.h" + +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <ctype.h> +#include <pwd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include <CoreServices/CoreServices.h> +#include <Carbon/Carbon.h> +#include <mach-o/dyld.h> + + +#define APP_PACKAGE_PATTERN ".app/Contents/MacOS/" +#define APP_PACKAGE "APP_PACKAGE" +#define JAVAROOT "JAVAROOT" + +static void debug(const char *fmt, ...); +static void dumpArgs(char *tag, int argc, char* argv[]); +static char *append(char *buffer, const char *s); +static char *appendc(char *buffer, char c); +static char *expandShell(char *arg, const char *appPackage, const char *javaRoot); +static char *my_strcasestr(const char *big, const char *little); + +static FILE *fgConsoleLog; +static char *fgAppPackagePath; +static int fgPid; + +extern int original_main(int argc, char* argv[]); +int main( int argc, char* argv[] ) { + + SInt32 systemVersion= 0; + if (Gestalt(gestaltSystemVersion, &systemVersion) == noErr) { + systemVersion &= 0xffff; +#ifdef COCOA + if (systemVersion < 0x1050) { + displayMessage("Error", "This application requires Mac OS X 10.5 (Leopard) or greater."); + return 0; + } +#else + if (systemVersion < 0x1020) { + displayMessage("Error", "This application requires Jaguar (Mac OS X >= 10.2)"); + return 0; + } +#endif + } + + fgConsoleLog= fopen("/dev/console", "w"); + fgPid= getpid(); + + dumpArgs("start", argc, argv); + if ( (argc > 1 && strncmp(argv[1], "-psn_", 5) == 0) || argc == 1) { + /* find path to application bundle (ignoring case) */ + char *pos= my_strcasestr(argv[0], APP_PACKAGE_PATTERN); + if (pos != NULL) { + int l= pos-argv[0] + 4; // reserve space for ".app" + fgAppPackagePath= malloc(l+1); + strncpy(fgAppPackagePath, argv[0], l); + fgAppPackagePath[l]= '\0'; // terminate result + } + + /* Get the main bundle for the app */ + CFBundleRef mainBundle= CFBundleGetMainBundle(); + if (mainBundle != NULL) { + + /* Get an instance of the info plist.*/ + CFDictionaryRef bundleInfoDict= CFBundleGetInfoDictionary(mainBundle); + + /* If we succeeded, look for our property. */ + if (bundleInfoDict != NULL) { + CFArrayRef ar= CFDictionaryGetValue(bundleInfoDict, CFSTR("Eclipse")); + if (ar) { + CFIndex size= CFArrayGetCount(ar); + if (size > 0) { + int i; + char **old_argv= argv; + argv= (char**) calloc(size+2, sizeof(char*)); + argc= 0; + argv[argc++]= old_argv[0]; + for (i= 0; i < size; i++) { + CFStringRef sr= (CFStringRef) CFArrayGetValueAtIndex (ar, i); + CFIndex argStringSize= CFStringGetMaximumSizeForEncoding(CFStringGetLength(sr), kCFStringEncodingUTF8); + char *s= malloc(argStringSize); + if (CFStringGetCString(sr, s, argStringSize, kCFStringEncodingUTF8)) { + argv[argc++]= expandShell(s, fgAppPackagePath, NULL); + } else { + fprintf(fgConsoleLog, "can't extract bytes\n"); + } + //free(s); + } + } + } else { + fprintf(fgConsoleLog, "no Eclipse dict found\n"); + } + } else { + fprintf(fgConsoleLog, "no bundle dict found\n"); + } + } else { + fprintf(fgConsoleLog, "no bundle found\n"); + } + } + int exitcode= original_main(argc, argv); + debug("<<<< exit(%d)\n", exitcode); + fclose(fgConsoleLog); + return exitcode; +} + +static void debug(const char *fmt, ...) { +#if DEBUG + va_list ap; + va_start(ap, fmt); + fprintf(fgConsoleLog, "%05d: ", fgPid); + vfprintf(fgConsoleLog, fmt, ap); + va_end(ap); +#endif +} + +static void dumpArgs(char *tag, int argc, char* argv[]) { +#if DEBUG + int i; + if (argc < 0) { + argc= 0; + for (i= 0; argv[i] != NULL; i++) + argc++; + } + debug(">>>> %s:", tag); + for (i= 0; i < argc && argv[i] != NULL; i++) + fprintf(fgConsoleLog, " <%s>", argv[i]); + fprintf(fgConsoleLog, "\n"); +#endif +} + +/* + * Expand $APP_PACKAGE, $JAVA_HOME, and does tilde expansion. + + A word beginning with an unquoted tilde character (~) is + subject to tilde expansion. All the characters up to a + slash (/) or the end of the word are treated as a username + and are replaced with the user's home directory. If the + username is missing (as in ~/foobar), the tilde is + replaced with the value of the HOME variable (the current + user's home directory). + */ +static char *expandShell(char *arg, const char *appPackage, const char *javaRoot) { + + if (index(arg, '~') == NULL && index(arg, '$') == NULL) + return arg; + + char *buffer= strdup(""); + char c, lastChar= ' '; + const char *cp= arg; + while ((c = *cp++) != 0) { + if (isspace(lastChar) && c == '~') { + char name[100], *dir= NULL; + int j= 0; + for (; (c = *cp) != 0; cp++) { + if (! isalnum(c)) + break; + name[j++]= c; + lastChar= c; + } + name[j]= '\0'; + if (j > 0) { + struct passwd *pw= getpwnam(name); + if (pw != NULL) + dir= pw->pw_dir; + } else { + dir= getenv("HOME"); + } + if (dir != NULL) + buffer= append(buffer, dir); + + } else if (c == '$') { + int l= strlen(APP_PACKAGE); + if (appPackage != NULL && strncmp(cp, APP_PACKAGE, l) == 0) { + cp+= l; + buffer= append(buffer, appPackage); + } else { + int l= strlen(JAVAROOT); + if (javaRoot != NULL && strncmp(cp, JAVAROOT, l) == 0) { + cp+= l; + buffer= append(buffer, javaRoot); + } else { + buffer= appendc(buffer, c); + } + } + } else + buffer= appendc(buffer, c); + lastChar= c; + } + return buffer; +} + +static char *my_strcasestr(const char *big, const char *little) { + char *cp, *s, *t; + for (cp= (char*) big; *cp; cp++) { + for (s= cp, t= (char*) little; *s && *t; s++, t++) + if (toupper(*s) != toupper(*t)) + break; + if (*t == '\0') + return cp; + } + return NULL; +} + +static char *append(char *buffer, const char *s) { + int bl= strlen(buffer); + int sl= strlen(s); + buffer= realloc(buffer, bl+sl+1); + strcpy(&buffer[bl], s); + return buffer; +} + +static char *appendc(char *buffer, char c) { + int bl= strlen(buffer); + buffer= realloc(buffer, bl+2); + buffer[bl++]= c; + buffer[bl]= '\0'; + return buffer; +}
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseMain.c b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseMain.c new file mode 100644 index 000000000..c0eaffa13 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/eclipseMain.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andre Weinand (OTI Labs) + */ + +#define main original_main + +#include "../eclipseMain.c" diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/make_carbon.mak b/features/org.eclipse.equinox.executable.feature/library/carbon/make_carbon.mak new file mode 100644 index 000000000..34843b739 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/make_carbon.mak @@ -0,0 +1,93 @@ +#********************************************************************** +# Copyright (c) 2000, 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Kevin Cornell (Rational Software Corporation) +#********************************************************************** +include ../make_version.mak +# Makefile for creating the Carbon eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch + +#default value for PROGRAM_OUTPUT +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +endif +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o eclipseCarbonMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseCarbonCommon.o +DLL_OBJS = eclipse.o eclipseCarbon.o eclipseUtil.o eclipseJNI.o eclipseShm.o NgImageData.o NgWinBMPFileFormat.o NgCommon.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -framework Carbon +ARCHS = -arch i386 -arch ppc +CFLAGS = -O -s \ + -mmacosx-version-min=10.3 \ + -Wall \ + $(ARCHS) \ + -DMACOSX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I.. -I../motif -I/System/Library/Frameworks/JavaVM.framework/Headers + +all: $(EXEC) $(DLL) + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseCarbonMain.o : eclipseCarbonMain.c + $(CC) $(CFLAGS) -c eclipseCarbonMain.c -o $@ + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h eclipseMain.c ../eclipseMain.c + $(CC) $(CFLAGS) -c eclipseMain.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +NgCommon.o: ../motif/NgCommon.c + $(CC) $(CFLAGS) -c ../motif/NgCommon.c -o $@ + +NgWinBMPFileFormat.o: ../motif/NgWinBMPFileFormat.c + $(CC) $(CFLAGS) -c ../motif/NgWinBMPFileFormat.c -o $@ + +NgImageData.o: ../motif/NgImageData.c + $(CC) $(CFLAGS) -c ../motif/NgImageData.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(ARCHS) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) -bundle -o $(DLL) $(ARCHS) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(PPC_OUTPUT_DIR) + cp $(EXEC) $(X86_OUTPUT_DIR) + rm -f $(EXEC) $(OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/carbon/make_cocoa.mak b/features/org.eclipse.equinox.executable.feature/library/carbon/make_cocoa.mak new file mode 100644 index 000000000..868c34bbf --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/carbon/make_cocoa.mak @@ -0,0 +1,97 @@ +#********************************************************************** +# Copyright (c) 2000, 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Kevin Cornell (Rational Software Corporation) +#********************************************************************** +include ../make_version.mak +# Makefile for creating the Carbon eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch + +#default value for PROGRAM_OUTPUT +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +endif +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o eclipseCarbonMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseCarbonCommon.o +DLL_OBJS = eclipse.o eclipseCarbon.o eclipseUtil.o eclipseJNI.o eclipseShm.o +#NgImageData.o NgWinBMPFileFormat.o NgCommon.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -framework Cocoa + +ifeq ($(ARCHS),) +ARCHS = -arch i386 -arch ppc +endif + +CFLAGS = -O -s \ + -Wall \ + -DCOCOA -xobjective-c \ + $(ARCHS) \ + -DMACOSX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I.. -I../motif -I/System/Library/Frameworks/JavaVM.framework/Headers + +all: $(EXEC) $(DLL) + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseCarbonMain.o : eclipseCarbonMain.c + $(CC) $(CFLAGS) -c eclipseCarbonMain.c -o $@ + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h eclipseMain.c ../eclipseMain.c + $(CC) $(CFLAGS) -c eclipseMain.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +NgCommon.o: ../motif/NgCommon.c + $(CC) $(CFLAGS) -c ../motif/NgCommon.c -o $@ + +NgWinBMPFileFormat.o: ../motif/NgWinBMPFileFormat.c + $(CC) $(CFLAGS) -c ../motif/NgWinBMPFileFormat.c -o $@ + +NgImageData.o: ../motif/NgImageData.c + $(CC) $(CFLAGS) -c ../motif/NgImageData.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(ARCHS) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) -bundle -o $(DLL) $(ARCHS) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp -v $(EXEC) $(PROGRAM_OUTPUT_DIR) + rm -f $(EXEC) $(OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipse.c b/features/org.eclipse.equinox.executable.feature/library/eclipse.c new file mode 100644 index 000000000..be01c9ccc --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipse.c @@ -0,0 +1,1781 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + * Markus Schorn (Wind River Systems), bug 193340 + * Martin Oberhuber (Wind River) - [149994] Add --launcher.appendVmargs + *******************************************************************************/ + +/* Eclipse Program Launcher + * + * This file forms the base of the eclipse_*.dll/so. This dll is loaded by eclipse.exe + * to start a Java VM, or alternatively it is loaded from Java to show the splash + * screen or write to the shared memory. See eclipseJNI.c for descriptions of the methods + * exposed to the Java program using JNI. + * + * To display a splash screen before starting the java vm, the launcher should be started + * with the location of the splash bitmap to use: + * -showsplash <path/to/splash.bmp> + * Otherwise, when the Java program starts, it should determine the location of + * the splash bitmap to be used and use the JNI method show_splash. + * + * When the Java program initialization is complete, the splash window + * is brought down by calling the JNI method takedown_splash. + * + * The Java program can also call the get_splash_handle method to get the handle to the splash + * window. This can be passed to SWT to create SWT widgets in the splash screen. + * + * The Java application will receive two other arguments: + * -exitdata <shared memory id> + * + * The java program can call set_exit_data with this shared-memory-id + * to provide specific exit data to the launcher. + * + * The exit data size must not exceed MAX_SHARED_LENGTH which is + * 16Kb. The interpretation of the exit data is dependent on the + * exit value of the java application. + * + * The main launcher recognizes the following exit codes from the + * Java application: + * + * 0 - Exit normally. + * RESTART_LAST_EC = 23 + * - restart the java VM again with the same arguments as the previous one. + * RESTART_NEW_EC = 24 + * - restart the java VM again with the arguments taken from the exit data. + * The exit data format is a list of arguments separated by '\n'. The Java + * application should build this list using the arguments passed to it on + * startup. See below. + * + * Additionally, if the Java application exits with an exit code other than the + * ones above, the main launcher will display an error message with the contents + * of the exit data. If the exit data is empty, a generic error message is + * displayed. The generic error message shows the exit code and the arguments + * passed to the Java application. + * + * The options that can be specified by the user to the launcher are: + * -vm <javaVM> the Java VM to be used + * -os <opSys> the operating system being run on + * -arch <osArch> the hardware architecture of the OS: x86, sparc, hp9000 + * -ws <gui> the window system to be used: win32, motif, gtk, ... + * -nosplash do not display the splash screen. The java application will + * not receive the -showsplash command. + * -showsplash <bitmap> show the given bitmap in the splash screen. + * -name <name> application name displayed in error message dialogs and + * splash screen window. Default value is computed from the + * name of the executable - with the first letter capitalized + * if possible. e.g. eclipse.exe defaults to the name Eclipse. + * -startup <startup.jar> the startup jar to execute. The argument is first assumed to be + * relative to the path of the launcher. If such a file does not + * exist, the argument is then treated as an absolute path. + * The default is find the plugins/org.eclipse.equinox.launcher jar + * with the highest version number. + * The jar must contain an org.eclipse.equinox.launcher.Main class. + * (unless JNI invocation is not being used, then the jar only needs to be + * an executable jar) + * -library the location of the eclipse launcher shared library (this library) to use + * By default, the launcher exe (see eclipseMain.c) finds + * <userArgs> arguments that are passed along to the Java application + * (i.e, -data <path>, -debug, -console, -consoleLog, etc) + * -vmargs <userVMargs> ... a list of arguments for the VM itself + * + * The -vmargs option and all user specified VM arguments must appear + * at the end of the command line, after all arguments that are + * being passed to Java application. + * + * The argument order for the new Java VM process is as follows: + * + * <javaVM> <all VM args> + * -os <user or default OS value> + * -ws <user or default WS value> + * -arch <user or default ARCH value> + * -launcher <absolute launcher name> + * -name <application name> + * -library <eclipse library location> + * -startup <startup.jar location> + * [-showsplash] + * [-exitdata <shared memory id>] + * <userArgs> + * -vm <javaVM> + * -vmargs <all VM args> + * + * where: + * <all VM args> = + * [<defaultVMargs | <userVMargs>] + * -jar + * <startup jar full path> + * + * The startup jar must be an executable jar. + * + * + * See "Main.java" for a simple implementation of the Java + * application. + * + * Configuration file + * The launcher gets arguments from the command line and/or from a configuration file. + * The configuration file must have the same name and location as the launcher executable + * and the extension .ini. For example, the eclipse.ini configuration file must be + * in the same folder as the eclipse.exe or eclipse executable. + * The format of the ini file matches that of the command line arguments - one + * argument per line. + * In general, the settings of the config file are expected to be overriden by the + * command line. + * - launcher arguments (-os, -arch...) set in the config file are overriden by the command line + * - the -vmargs from the command line replaces in its entirety the -vmargs from the config file. + * - user arguments from the config file are prepended to the user arguments defined in the + * config file. This is consistent with the java behaviour in the following case: + * java -Dtest="one" -Dtest="two" ... : test is set to the value "two" + */ + +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include "eclipseShm.h" +#include "eclipseJNI.h" +#include "eclipseConfig.h" +#include "eclipseCommon.h" + +#ifdef _WIN32 +#include <windows.h> +#include <direct.h> +#include <io.h> +#include <fcntl.h> +#else +#include <unistd.h> +#include <strings.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <ctype.h> + +#define MAX_PATH_LENGTH 2000 +#define MAX_SHARED_LENGTH (16 * 1024) + +/* Global Data */ +static _TCHAR* program = NULL; /* full pathname of the program */ +static _TCHAR* programDir = NULL; /* directory where program resides */ +static _TCHAR* javaVM = NULL; /* full pathname of the Java VM to run */ +static _TCHAR* jniLib = NULL; /* full path of a java vm library for JNI invocation */ +static _TCHAR* jarFile = NULL; /* full pathname of the startup jar file to run */ +static _TCHAR* sharedID = NULL; /* ID for the shared memory */ +static _TCHAR* officialName = NULL; + +_TCHAR* exitData = NULL; /* exit data set from Java */ +int initialArgc; +_TCHAR** initialArgv = NULL; + + +/* Define the special exit codes returned from Eclipse. */ +#define RESTART_LAST_EC 23 +#define RESTART_NEW_EC 24 + +/* constants for launch mode */ +#define LAUNCH_JNI 1 +#define LAUNCH_EXE 2 + +#define DEFAULT_EE _T_ECLIPSE("default.ee") + +/* Define error messages. (non-NLS) */ +static _TCHAR* exitMsg = _T_ECLIPSE("JVM terminated. Exit code=%d\n%s"); +static _TCHAR* javaFailureMsg = _T_ECLIPSE("Internal Error, unable to determine the results of running the JVM."); +static _TCHAR* returnCodeMsg = _T_ECLIPSE("Java was started but returned exit code=%d\n%s"); +static _TCHAR* goVMMsg = _T_ECLIPSE("Start VM: %s\n"); +static _TCHAR* pathMsg = _T_ECLIPSE("%s in your current PATH"); +static _TCHAR* shareMsg = _T_ECLIPSE("No exit data available."); +static _TCHAR* noVMMsg = +_T_ECLIPSE("A Java Runtime Environment (JRE) or Java Development Kit (JDK)\n\ +must be available in order to run %s. No Java virtual machine\n\ +was found after searching the following locations:\n\ +%s"); +static _TCHAR* startupMsg = +_T_ECLIPSE("The %s executable launcher was unable to locate its \n\ +companion launcher jar."); + +static _TCHAR* homeMsg = +_T_ECLIPSE("The %s executable launcher was unable to locate its \n\ +home directory."); + +#define OLD_STARTUP _T_ECLIPSE("startup.jar") +#define CLASSPATH_PREFIX _T_ECLIPSE("-Djava.class.path=") + +/* Define constants for the options recognized by the launcher. */ +#define CONSOLE _T_ECLIPSE("-console") +#define CONSOLELOG _T_ECLIPSE("-consoleLog") +#define DEBUG _T_ECLIPSE("-debug") +#define OS _T_ECLIPSE("-os") +#define OSARCH _T_ECLIPSE("-arch") +#define NOSPLASH _T_ECLIPSE("-nosplash") +#define LAUNCHER _T_ECLIPSE("-launcher") +#define SHOWSPLASH _T_ECLIPSE("-showsplash") +#define EXITDATA _T_ECLIPSE("-exitdata") +#define STARTUP _T_ECLIPSE("-startup") +#define VM _T_ECLIPSE("-vm") +#define WS _T_ECLIPSE("-ws") +#define NAME _T_ECLIPSE("-name") +#define VMARGS _T_ECLIPSE("-vmargs") /* special option processing required */ +#define CP _T_ECLIPSE("-cp") +#define CLASSPATH _T_ECLIPSE("-classpath") +#define JAR _T_ECLIPSE("-jar") + +#define OPENFILE _T_ECLIPSE("--launcher.openFile") +#define DEFAULTACTION _T_ECLIPSE("--launcher.defaultAction") +#define TIMEOUT _T_ECLIPSE("--launcher.timeout") +#define LIBRARY _T_ECLIPSE("--launcher.library") +#define SUPRESSERRORS _T_ECLIPSE("--launcher.suppressErrors") +#define INI _T_ECLIPSE("--launcher.ini") +#define APPEND_VMARGS _T_ECLIPSE("--launcher.appendVmargs") +#define OVERRIDE_VMARGS _T_ECLIPSE("--launcher.overrideVmargs") +#define SECOND_THREAD _T_ECLIPSE("--launcher.secondThread") +#define PERM_GEN _T_ECLIPSE("--launcher.XXMaxPermSize") + +#define XXPERMGEN _T_ECLIPSE("-XX:MaxPermSize=") +#define ACTION_OPENFILE _T_ECLIPSE("openFile") + +/* constants for ee options file */ +#define EE_EXECUTABLE _T_ECLIPSE("-Dee.executable=") +#define EE_CONSOLE _T_ECLIPSE("-Dee.executable.console=") +#define EE_VM_LIBRARY _T_ECLIPSE("-Dee.vm.library=") +#define EE_LIBRARY_PATH _T_ECLIPSE("-Dee.library.path=") +#define EE_HOME _T_ECLIPSE("-Dee.home=") +#define EE_FILENAME _T_ECLIPSE("-Dee.filename=") +#define EE_HOME_VAR _T_ECLIPSE("${ee.home}") + +/* Define the variables to receive the option values. */ +static int needConsole = 0; /* True: user wants a console */ +static int debug = 0; /* True: output debugging info */ +static int noSplash = 0; /* True: do not show splash win */ +static int suppressErrors = 0; /* True: do not display errors dialogs */ + int secondThread = 0; /* True: start the VM on a second thread */ +static int appendVmargs = 0; /* True: append cmdline vmargs to launcher.ini vmargs */ + +static _TCHAR* showSplashArg = NULL; /* showsplash data (main launcher window) */ +static _TCHAR* splashBitmap = NULL; /* the actual splash bitmap */ +static _TCHAR * startupArg = NULL; /* path of the startup.jar the user wants to run relative to the program path */ +static _TCHAR* vmName = NULL; /* Java VM that the user wants to run */ +static _TCHAR* name = NULL; /* program name */ +static _TCHAR* permGen = NULL; /* perm gen size for sun */ +static _TCHAR** filePath = NULL; /* list of files to open */ +static _TCHAR* timeoutString = NULL; /* timeout value for opening a file */ +static _TCHAR* defaultAction = NULL; /* default action for non '-' command line arguments */ +static _TCHAR* iniFile = NULL; /* the launcher.ini file set if --launcher.ini was specified */ + +/* variables for ee options */ +static _TCHAR* eeExecutable = NULL; +static _TCHAR* eeConsole = NULL; +static _TCHAR* eeLibrary = NULL; + +_TCHAR* eeLibPath = NULL; /* this one is global so others can see it */ +_TCHAR* eclipseLibrary = NULL; /* the shared library */ + +/* Define a table for processing command line options. */ +typedef struct +{ + _TCHAR* name; /* the option recognized by the launcher */ + void* value; /* the variable where the option value is saved */ + /* value is a _TCHAR** or int* depending on if VALUE_IS_FLAG is set */ + int flag; /* flags */ + int remove; /* the number of argments to remove from the list, -1 can be used with VALUE_IS_LIST */ +} Option; + +/* flags for the Option struct */ +#define VALUE_IS_FLAG 1 /* value is an int*, if not set, value is a _TCHAR** or _TCHAR*** (VALUE_IS_LIST) */ +#define OPTIONAL_VALUE 2 /* value is optional, if next arg does not start with '-', */ + /* don't assign it and only remove (remove - 1) arguments */ +#define ADJUST_PATH 4 /* value is a path, do processing on relative paths to try and make them absolute */ +#define VALUE_IS_LIST 8 /* value is a pointer to a tokenized _TCHAR* string for EE files, or a _TCHAR** list for the command line */ +#define INVERT_FLAG 16 /* invert the meaning of a flag, i.e. reset it */ + +static Option options[] = { + { CONSOLE, &needConsole, VALUE_IS_FLAG, 0 }, + { CONSOLELOG, &needConsole, VALUE_IS_FLAG, 0 }, + { DEBUG, &debug, VALUE_IS_FLAG, 0 }, + { NOSPLASH, &noSplash, VALUE_IS_FLAG, 1 }, + { SUPRESSERRORS, &suppressErrors, VALUE_IS_FLAG, 1}, + { SECOND_THREAD, &secondThread, VALUE_IS_FLAG, 1 }, + { APPEND_VMARGS, &appendVmargs, VALUE_IS_FLAG, 1 }, + { OVERRIDE_VMARGS, &appendVmargs, VALUE_IS_FLAG | INVERT_FLAG, 1 }, + { LIBRARY, NULL, 0, 2 }, /* library was parsed by exe, just remove it */ + { INI, &iniFile, 0, 2 }, + { OS, &osArg, 0, 2 }, + { OSARCH, &osArchArg, 0, 2 }, + { SHOWSPLASH, &showSplashArg, OPTIONAL_VALUE, 2 }, + { STARTUP, &startupArg, 0, 2 }, + { VM, &vmName, 0, 2 }, + { NAME, &name, 0, 2 }, + { PERM_GEN, &permGen, 0, 2 }, + { OPENFILE, &filePath, ADJUST_PATH | VALUE_IS_LIST, -1 }, + { TIMEOUT, &timeoutString, 0, 2 }, + { DEFAULTACTION,&defaultAction, 0, 2 }, + { WS, &wsArg, 0, 2 } }; +static int optionsSize = (sizeof(options) / sizeof(options[0])); + +static Option eeOptions[] = { + { EE_EXECUTABLE, &eeExecutable, ADJUST_PATH, 0 }, + { EE_CONSOLE, &eeConsole, ADJUST_PATH, 0 }, + { EE_VM_LIBRARY, &eeLibrary, ADJUST_PATH, 0 }, + { EE_LIBRARY_PATH, &eeLibPath, ADJUST_PATH | VALUE_IS_LIST, 0 } +}; +static int eeOptionsSize = (sizeof(eeOptions) / sizeof(eeOptions[0])); + +/* Define the required VM arguments (all platforms). */ +static _TCHAR* cp = NULL; +static _TCHAR* cpValue = NULL; +static _TCHAR** reqVMarg[] = { &cp, &cpValue, NULL }; /* required VM args */ +static _TCHAR** userVMarg = NULL; /* user specific args for the Java VM */ +static _TCHAR** eeVMarg = NULL; /* vm args specified in ee file */ +static int nEEargs = 0; + +/* Local methods */ +static void parseArgs( int* argc, _TCHAR* argv[] ); +static void processDefaultAction(int argc, _TCHAR* argv[]); +static void mergeUserVMArgs( _TCHAR **vmArgs[] ); +static void getVMCommand( int launchMode, int argc, _TCHAR* argv[], _TCHAR **vmArgv[], _TCHAR **progArgv[] ); +static int determineVM(_TCHAR** msg); +static int vmEEProps(_TCHAR* eeFile, _TCHAR** msg); +static int processEEProps(_TCHAR* eeFile); +static _TCHAR** buildLaunchCommand( _TCHAR* program, _TCHAR** vmArgs, _TCHAR** progArgs ); +static _TCHAR** parseArgList( _TCHAR *data ); +static _TCHAR* formatVmCommandMsg( _TCHAR* args[], _TCHAR* vmArgs[], _TCHAR* progArgs[] ); +static _TCHAR* getDefaultOfficialName(); +static _TCHAR* findStartupJar(); +static _TCHAR* findSplash(_TCHAR* splashArg); +static _TCHAR** getRelaunchCommand( _TCHAR **vmCommand ); +static const _TCHAR* getVMArch(); + +#ifdef _WIN32 +static void createConsole(); +static void fixDLLSearchPath(); +static int isConsoleLauncher(); +#endif +static int consoleLauncher = 0; + +/* Record the arguments that were used to start the original executable */ +JNIEXPORT void setInitialArgs(int argc, _TCHAR** argv, _TCHAR* lib) { + initialArgc = argc; + initialArgv = argv; + eclipseLibrary = lib; +} + +/* this method must match the RunMethod typedef in eclipseMain.c */ +/* vmArgs must be NULL terminated */ +JNIEXPORT int run(int argc, _TCHAR* argv[], _TCHAR* vmArgs[]) +{ + _TCHAR** vmCommand = NULL; + _TCHAR** vmCommandArgs = NULL; + _TCHAR** progCommandArgs = NULL; + _TCHAR** relaunchCommand = NULL; + _TCHAR* errorMsg = NULL, *msg = NULL; + JavaResults* javaResults = NULL; + int launchMode; + int running = 1; + + /* arg[0] should be the full pathname of this program. */ + program = _tcsdup( argv[0] ); + + /* Parse command line arguments (looking for the VM to use). */ + /* Override configuration file arguments */ + parseArgs( &argc, argv ); + + /* Initialize official program name */ + officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName(); + + if (defaultAction != NULL) { + processDefaultAction(initialArgc, initialArgv); + } + + /* try to open the specified file in an already running eclipse */ + /* on Mac we are only registering an event handler here, always do this */ +#ifndef MACOSX + if (filePath != NULL && filePath[0] != NULL) +#endif + { + int timeout = 60; + if (timeoutString != NULL) + _stscanf(timeoutString, _T_ECLIPSE("%d"), &timeout); + if (reuseWorkbench(filePath, timeout) > 0) + return 0; + } + +#ifdef MACOSX + /* Most platforms, we will initialize the window system later before trying to do any + * graphics. On Mac, we need it initialized to get the dock icon properly, so always do + * it now. + */ + initWindowSystem( &argc, argv, !noSplash ); +#elif _WIN32 + /* this must be before doing any console stuff, platforms other than win32 leave this set to 0 */ + consoleLauncher = isConsoleLauncher(); + + /*fix the DLL search path for security */ + fixDLLSearchPath(); +#endif + + /* Find the directory where the Eclipse program is installed. */ + programDir = getProgramDir(); + if (programDir == NULL) + { + errorMsg = malloc( (_tcslen(homeMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) ); + _stprintf( errorMsg, homeMsg, officialName ); + if (!suppressErrors) + displayMessage( officialName, errorMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, errorMsg); + free( errorMsg ); + exit( 1 ); + } + + if (vmArgs != NULL) { + /* reconcile VM Args from commandline with launcher.ini (append or override), + * this always allocates new memory */ + mergeUserVMArgs(&vmArgs); + /* platform specific processing of user's vmargs */ + processVMArgs(&vmArgs); + } + + launchMode = determineVM(&msg); + if (launchMode == -1) { + /* problem */ + errorMsg = malloc((_tcslen(noVMMsg) + _tcslen(officialName) + _tcslen(msg) + 1) * sizeof(_TCHAR)); + _stprintf( errorMsg, noVMMsg, officialName, msg ); + if (!suppressErrors) + displayMessage( officialName, errorMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, errorMsg); + free( errorMsg ); + free( msg ); + exit(1); + } + + /* Find the startup.jar */ + jarFile = findStartupJar(); + if(jarFile == NULL) { + errorMsg = malloc( (_tcslen(startupMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) ); + _stprintf( errorMsg, startupMsg, officialName ); + if (!suppressErrors) + displayMessage( officialName, errorMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, errorMsg); + free( errorMsg ); + exit( 1 ); + } + +#ifdef _WIN32 + if( launchMode == LAUNCH_JNI && (debug || needConsole) ) { + createConsole(); + } +#endif + + /* If the showsplash option was given and we are using JNI */ + if (!noSplash && showSplashArg) + { + splashBitmap = findSplash(showSplashArg); + if (splashBitmap != NULL && launchMode == LAUNCH_JNI) { + showSplash(splashBitmap); + } + } + + /* not using JNI launching, need some shared data */ + if (launchMode == LAUNCH_EXE && createSharedData( &sharedID, MAX_SHARED_LENGTH )) { + if (debug) { + if (!suppressErrors) + displayMessage( officialName, shareMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, shareMsg); + } + } + + /* the startup jarFile goes on the classpath */ + if (launchMode == LAUNCH_JNI) { + /* JNI launching, classpath is set using -Djava.class.path */ + cp = malloc((_tcslen(CLASSPATH_PREFIX) + _tcslen(jarFile) + 1) * sizeof(_TCHAR)); + cp = _tcscpy(cp, CLASSPATH_PREFIX); + _tcscat(cp, jarFile); + } else { + /* exec java, jar is specified with -jar */ + cp = JAR; + cpValue = malloc((_tcslen(jarFile) + 1) * sizeof(_TCHAR)); + _tcscpy(cpValue, jarFile); + } + + /* Get the command to start the Java VM. */ + userVMarg = vmArgs; + getVMCommand( launchMode, argc, argv, &vmCommandArgs, &progCommandArgs ); + + if (launchMode == LAUNCH_EXE) { + vmCommand = buildLaunchCommand(javaVM, vmCommandArgs, progCommandArgs); + } + + /* While the Java VM should be restarted */ + while(running) + { + msg = formatVmCommandMsg( vmCommand, vmCommandArgs, progCommandArgs ); + if (debug) _tprintf( goVMMsg, msg ); + + if(launchMode == LAUNCH_JNI) { + javaResults = startJavaVM(jniLib, vmCommandArgs, progCommandArgs, jarFile); + } else { + javaResults = launchJavaVM(vmCommand); + } + + if (javaResults == NULL) { + /* shouldn't happen, but just in case */ + javaResults = malloc(sizeof(JavaResults)); + javaResults->launchResult = -11; + javaResults->runResult = 0; + javaResults->errorMessage = _tcsdup(javaFailureMsg); + } + + switch( javaResults->launchResult + javaResults->runResult ) { + case 0: /* normal exit */ + running = 0; + break; + case RESTART_LAST_EC: + if (launchMode == LAUNCH_JNI) { + /* copy for relaunch, +1 to ensure NULL terminated */ + relaunchCommand = malloc((initialArgc + 1) * sizeof(_TCHAR*)); + memcpy(relaunchCommand, initialArgv, (initialArgc + 1) * sizeof(_TCHAR*)); + relaunchCommand[initialArgc] = 0; + relaunchCommand[0] = program; + running = 0; + } + break; + + case RESTART_NEW_EC: + if(launchMode == LAUNCH_EXE) { + if (exitData != NULL) free(exitData); + if (getSharedData( sharedID, &exitData ) != 0) + exitData = NULL; + } + if (exitData != 0) { + if (vmCommand != NULL) free( vmCommand ); + vmCommand = parseArgList( exitData ); + if (launchMode == LAUNCH_JNI) { + relaunchCommand = getRelaunchCommand(vmCommand); + running = 0; + } + } else { + running = 0; + if (debug) { + if (!suppressErrors) + displayMessage( officialName, shareMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, shareMsg); + } + } + break; + default: { + _TCHAR *title = _tcsdup(officialName); + running = 0; + errorMsg = NULL; + if (launchMode == LAUNCH_EXE) { + if (exitData != NULL) free(exitData); + if (getSharedData( sharedID, &exitData ) != 0) + exitData = NULL; + } + if (exitData != 0) { + errorMsg = exitData; + exitData = NULL; + if (_tcslen( errorMsg ) > 0) { + _TCHAR *str; + if (_tcsncmp(errorMsg, _T_ECLIPSE("<title>"), _tcslen(_T_ECLIPSE("<title>"))) == 0) { + str = _tcsstr(errorMsg, _T_ECLIPSE("</title>")); + if (str != NULL) { + free( title ); + str[0] = _T_ECLIPSE('\0'); + title = _tcsdup( errorMsg + _tcslen(_T_ECLIPSE("<title>")) ); + str = _tcsdup( str + _tcslen(_T_ECLIPSE("</title>")) ); + free( errorMsg ); + errorMsg = str; + } + } + } + } else { + if (debug) { + if (!suppressErrors) + displayMessage( title, shareMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), title, shareMsg); + } + } + if (errorMsg == NULL) { + if (javaResults->runResult) { + /* java was started ok, but returned non-zero exit code */ + errorMsg = malloc( (_tcslen(returnCodeMsg) + _tcslen(msg) + 10) *sizeof(_TCHAR)); + _stprintf(errorMsg, returnCodeMsg,javaResults->runResult, msg); + } else if (javaResults->errorMessage != NULL){ + /* else we had a problem launching java, use custom error message */ + errorMsg = javaResults->errorMessage; + } else { + /* no custom message, use generic message */ + errorMsg = malloc( (_tcslen(exitMsg) + _tcslen(msg) + 10) * sizeof(_TCHAR) ); + _stprintf( errorMsg, exitMsg, javaResults->launchResult, msg ); + } + } + + if (_tcslen(errorMsg) > 0) { + if (!suppressErrors) + displayMessage( title, errorMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), title, errorMsg); + } + free( errorMsg ); + free( title ); + break; + } + } + free( msg ); + } + + if(relaunchCommand != NULL) + restartLauncher(NULL, relaunchCommand); + + if (launchMode == LAUNCH_JNI) + cleanupVM(javaResults->launchResult ? javaResults->launchResult : javaResults->runResult); + + if (sharedID != NULL) { + destroySharedData( sharedID ); + free( sharedID ); + } + + /* Cleanup time. */ + free( vmCommandArgs ); + free( progCommandArgs ); + free( jarFile ); + free( programDir ); + free( program ); + free( officialName ); + if(vmCommand != NULL) free(vmCommand); + if(launchMode == LAUNCH_JNI) free(cp); + if(cpValue != NULL) free(cpValue); + if(exitData != NULL) free(exitData); + if(splashBitmap != NULL) free(splashBitmap); + if(vmArgs != NULL) free(vmArgs); + + if (javaResults == NULL) + return -1; + + /* reuse the running variable for convenience */ + running = javaResults->launchResult != 0 ? javaResults->launchResult : javaResults->runResult; + free(javaResults); + return running; +} + +static _TCHAR** buildLaunchCommand( _TCHAR* program, _TCHAR** vmArgs, _TCHAR** progArgs ) { + int nVM = -1, nProg = -1; + _TCHAR** result; + + while(vmArgs[++nVM] != NULL) {} + while(progArgs[++nProg] != NULL) {} + + result = malloc((nVM + nProg + 2) * sizeof(_TCHAR*)); + memset(result, 0, (nVM + nProg + 2) * sizeof(_TCHAR*)); + result[0] = program; + memcpy(result + 1, vmArgs, nVM * sizeof(_TCHAR*)); + memcpy(result + 1 + nVM, progArgs, nProg * sizeof(_TCHAR*)); + return result; +} + +static void processDefaultAction(int argc, _TCHAR* argv[]) { + /* scan the arg list, no default if any start with '-' */ + int i = 0; + for (i = 0; i < argc; i++) { + if (argv[i][0] == _T_ECLIPSE('-')) + return; + } + /* argv[0] is the program (eclipse), we process the default actions by inserting + * the appropriate -argument at argv[1] + */ + if (argc <= 1) + return; + + if (_tcsicmp(defaultAction, ACTION_OPENFILE) == 0) { + int newArgc = argc + 1; + _TCHAR ** newArgv = malloc((newArgc + 1) * sizeof(_TCHAR*)); + newArgv[0] = argv[0]; + newArgv[1] = OPENFILE; + memcpy(&newArgv[2], &argv[1], argc * sizeof(_TCHAR*)); + parseArgs(&newArgc, newArgv); + free(newArgv); + } +} + +/* + * Parse arguments of the command. + */ +static void parseArgs(int* pArgc, _TCHAR* argv[]) { + Option* option; + int remArgs; + int index; + int i; + _TCHAR * c; + + /* For each user defined argument (excluding the program) */ + for (index = 1; index < *pArgc; index++) { + remArgs = 0; + + /* Find the corresponding argument is a option supported by the launcher */ + option = NULL; + for (i = 0; option == NULL && i < optionsSize; i++) { + if (_tcsicmp(argv[index], options[i].name) == 0) { + option = &options[i]; + break; + } + } + + /* If the option is recognized by the launcher */ + if (option != NULL) { + int optional = 0; + c = option->name; + /* If the option requires a value and there is one, extract the value. */ + if (option->value != NULL) { + if (option->flag & VALUE_IS_FLAG) + *((int *) option->value) = (option->flag & INVERT_FLAG) ? 0 : 1; + else { + int count = 1; + if (option->flag & VALUE_IS_LIST) { + /* count how many args, this is the -argument itself + following the non'-' args */ + while (count + index < *pArgc && argv[count + index][0] != _T_ECLIPSE('-')) + count++; + + /* allocate memory for a _TCHAR* list and initialize it with NULLs*/ + *((void**) option->value) = malloc(count * sizeof(_TCHAR *)); + memset(*((void **) option->value), 0, count * sizeof(_TCHAR *)); + + if (option->remove != 0) + option->remove = count; + } + + for (i = 0; i < count; i++) { + if ((index + i + 1) < *pArgc) { + _TCHAR * next = argv[index + i + 1]; + if (option->flag & ADJUST_PATH) + next = checkPath(next, getProgramDir(), 0); + if (next[0] != _T_ECLIPSE('-')) { + if (option->flag & VALUE_IS_LIST) + (*((_TCHAR***) option->value))[i] = next; + else + *((_TCHAR**) option->value) = next; + } else if (option->flag & OPTIONAL_VALUE) { + /* value was optional, and the next arg starts with '-' */ + optional = 1; + } + } + } + } + } + + /* If the option requires a flag to be set, set it. */ + remArgs = option->remove - optional; + } + + /* Remove any matched arguments from the list. */ + if (remArgs > 0) { + for (i = (index + remArgs); i <= *pArgc; i++) { + argv[i - remArgs] = argv[i]; + } + index--; + *pArgc -= remArgs; + } + } +} + +/* + * Parse the data into a list of arguments separated by \n. + */ +static _TCHAR** parseArgList( _TCHAR* data ) { + int totalArgs = 0, dst = 0; + size_t length; + _TCHAR *ch1, *ch2, **execArg; + length = _tcslen( data ); + ch1 = ch2 = data; + while ((ch2 = _tcschr( ch1, _T_ECLIPSE('\n') )) != NULL) { + totalArgs++; + ch1 = ch2 + 1; + } + if (ch1 != data + length) totalArgs++; + execArg = malloc( (totalArgs + 1) * sizeof( _TCHAR* ) ); + ch1 = ch2 = data; + while ((ch2 = _tcschr( ch1, _T_ECLIPSE('\n') )) != NULL) { + execArg[ dst++ ] = ch1; + ch2[ 0 ] = _T_ECLIPSE('\0'); + ch1 = ch2 + 1; + } + if (ch1 != data + length) execArg[ dst++ ] = ch1; + execArg[ dst++ ] = NULL; + return execArg; +} + +/* Return the list of args from the launcher ini file (if it exists). Caller is responsible to free(). */ +static _TCHAR** getConfigArgs() { + _TCHAR** configArgv = NULL; + _TCHAR * configFile = NULL; + int configArgc = 0; + int ret = 0; + + configFile = (iniFile != NULL) ? iniFile : getIniFile(program, consoleLauncher); + ret = readConfigFile(configFile, &configArgc, &configArgv); + if (ret == 0) + return configArgv; + return NULL; +} + +/** Append Commandline VM Args to VM Args that came from the launcher.ini + * Always returns new memory even if no new arguments were appended */ +static void mergeUserVMArgs(_TCHAR **vmArgs[]) { + _TCHAR** configVMArgs = NULL; + _TCHAR** configArgs = NULL; + + if (appendVmargs != 0 && indexOf(VMARGS, initialArgv) > 0) { + /* Get vmargs from the launcher.ini, if any */ + configArgs = getConfigArgs(); + if (configArgs != NULL) { + int vmArg = indexOf(VMARGS, configArgs); + if (vmArg >= 0) + configVMArgs = configArgs + vmArg + 1; + } + } + + /* This always allocates new memory so we don't need to guess if it is safe + * to free later */ + *vmArgs = concatArgs(configVMArgs, *vmArgs); + if (configArgs != NULL) + free(configArgs); +} + +static void adjustVMArgs(_TCHAR *javaVM, _TCHAR *jniLib, _TCHAR **vmArgv[]) { + /* Sun VMs need some extra perm gen space */ + /* Detecting Sun VM is expensive - only do so if necessary */ + if (permGen != NULL) { + int specified = 0, i = -1; + + /* first check to see if it is already specified */ + while ((*vmArgv)[++i] != NULL) { + /* we are also counting the number of args here */ + if (!specified && _tcsncmp((*vmArgv)[i], XXPERMGEN, _tcslen(XXPERMGEN)) == 0) { + specified = 1; + } + } + + if (!specified && isSunVM(javaVM, jniLib)) { + _TCHAR ** oldArgs = *vmArgv; + _TCHAR *newArg = malloc((_tcslen(XXPERMGEN) + _tcslen(permGen) + 1) * sizeof(_TCHAR)); + _stprintf(newArg, _T_ECLIPSE("%s%s"), XXPERMGEN, permGen); + + *vmArgv = malloc((i + 2) * sizeof(_TCHAR *)); + memcpy(*vmArgv, oldArgs, i * sizeof(_TCHAR *)); + (*vmArgv)[i] = newArg; + (*vmArgv)[i + 1] = 0; + } + } +} + +/* + * Get the command and arguments to start the Java VM. + * + * Memory allocated by this function is assumed to be + * deallocated when the program terminates. + * + * Some of the arguments returned by this function were + * passed directly from the main( argv ) array so they + * should not be deallocated. + * + * Arguments are split into 2: vm arguments and program arguments + */ +static void getVMCommand( int launchMode, int argc, _TCHAR* argv[], _TCHAR **vmArgv[], _TCHAR **progArgv[] ) +{ + _TCHAR** vmArg; + int nReqVMarg = 0; + int nVMarg = 0; + int totalVMArgs; + int totalProgArgs; + int src; + int dst; + + /* If the user specified "-vmargs", add them instead of the default VM args. */ + vmArg = (userVMarg != NULL) ? userVMarg : getArgVM( (launchMode == LAUNCH_JNI) ? jniLib : javaVM ); + + adjustVMArgs(javaVM, jniLib, &vmArg); + + /* Calculate the number of VM arguments. */ + while (vmArg[ nVMarg ] != NULL) + nVMarg++; + + /* Calculate the number of required VM arguments. */ + while (reqVMarg[ nReqVMarg ] != NULL) + nReqVMarg++; + + /* VM argument list */ + totalVMArgs = nVMarg + nReqVMarg + nEEargs + 1; + *vmArgv = malloc( totalVMArgs * sizeof(_TCHAR*) ); + + dst = 0; + for (src = 0; src < nVMarg; src++){ + /*if the user specified a classpath, skip it */ + if(_tcscmp(vmArg[src], cp) == 0){ + src++; + continue; + } + (*vmArgv)[ dst++ ] = vmArg[ src ]; + } + + if (eeVMarg != NULL) + for (src = 0; src < nEEargs; src++) + (*vmArgv)[ dst++ ] = eeVMarg[ src ]; + + /* For each required VM arg */ + for (src = 0; src < nReqVMarg; src++) + if( *(reqVMarg[src]) != NULL) + (*vmArgv)[ dst++ ] = *(reqVMarg[ src ]); + + + (*vmArgv)[dst] = NULL; + + /* Program arguments */ + /* OS <os> + WS <ws> + ARCH <arch> + LAUNCHER <launcher> + NAME <officialName> + + * + LIBRARY <library> + SHOWSPLASH <cmd> + EXITDATA <cmd> + STARTUP <jar> + OVERRIDE/APPEND + argv[] + VM + <vm> + + * VMARGS + vmArg + requiredVMargs + * + NULL) + */ + totalProgArgs = 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + argc + 2 + 1 + nVMarg + nEEargs + nReqVMarg + 1; + *progArgv = malloc( totalProgArgs * sizeof( _TCHAR* ) ); + dst = 0; + + /* Append the required options. */ + (*progArgv)[ dst++ ] = OS; + (*progArgv)[ dst++ ] = osArg; + (*progArgv)[ dst++ ] = WS; + (*progArgv)[ dst++ ] = wsArg; + if (_tcslen(osArchArg) > 0) { + (*progArgv)[ dst++ ] = OSARCH; + (*progArgv)[ dst++ ] = osArchArg; + } + + /* Append the show splash window command, if defined. */ + if (!noSplash) + { + (*progArgv)[ dst++ ] = SHOWSPLASH; + if(splashBitmap != NULL) + (*progArgv)[ dst++ ] = splashBitmap; + } + + /* Append the launcher command */ + (*progArgv)[ dst++ ] = LAUNCHER; + (*progArgv)[ dst++ ] = program; + + /* Append the name command */ + (*progArgv)[ dst++ ] = NAME; + (*progArgv)[ dst++ ] = officialName; + + /* And the shared library */ + if (eclipseLibrary != NULL) { + (*progArgv)[ dst++ ] = LIBRARY; + (*progArgv)[ dst++ ] = eclipseLibrary; + } + + /* the startup jar */ + (*progArgv)[ dst++ ] = STARTUP; + (*progArgv)[ dst++ ] = jarFile; + + /* override or append vm args */ + (*progArgv)[ dst++ ] = appendVmargs ? APPEND_VMARGS : OVERRIDE_VMARGS; + + /* Append the exit data command. */ + if (sharedID) { + (*progArgv)[ dst++ ] = EXITDATA; + (*progArgv)[ dst++ ] = sharedID; + } + + /* Append the remaining user defined arguments. */ + for (src = 1; src < argc; src++) + { + (*progArgv)[ dst++ ] = argv[ src ]; + } + + /* Append VM and VMARGS to be able to relaunch using exit data. */ + (*progArgv)[ dst++ ] = VM; + if(jniLib != NULL) + (*progArgv)[ dst++ ] = jniLib; + else + (*progArgv)[ dst++ ] = javaVM; + (*progArgv)[ dst++ ] = VMARGS; + + for (src = 0; src < nVMarg; src++) + (*progArgv)[ dst++ ] = vmArg[ src ]; + + if (eeVMarg != NULL) + for (src = 0; src < nEEargs; src++) + (*progArgv)[ dst++ ] = eeVMarg[ src ]; + + /* For each required VM arg */ + for (src = 0; src < nReqVMarg; src++) + if (*(reqVMarg[src]) != NULL) + (*progArgv)[ dst++ ] = *(reqVMarg[ src ]); + + (*progArgv)[ dst++ ] = NULL; + + } + + /* Format the JVM start command for error messages + * + * This method formats a string with the JVM start command (and all arguments) + * that can be used in displaying error messages. The string returned from this + * method is probably not NLS compliant and must be deallocated by the caller. + * + * The arguments in the message are either args (if not null) or the combination + * of vmArgs + progArgs + */ +static _TCHAR* formatVmCommandMsg( _TCHAR* args[], _TCHAR* vmArgs[], _TCHAR* progArgs[] ) +{ + int index; + size_t length = 0; + _TCHAR** list; + _TCHAR* ch; + _TCHAR* message; + + /* Determine the length of the message buffer. */ + if(args != NULL) list = args; + else list = vmArgs; + while(list != NULL) { + for (index = 0; list[index] != NULL; index++) + { + length += _tcslen(list[index]) + 1; + } + if(list == vmArgs) list = progArgs; + else list = NULL; + } + message = malloc( (length + 5) * sizeof(_TCHAR) ); + + /* Format the message such that options (args starting with '-') begin + on a new line. Otherwise, the Motif MessageBox does not automatically wrap + the messages and the message window can extend beyond both sides of the display. */ + ch = message; + if(args != NULL) list = args; + else list = vmArgs; + while(list != NULL) { + for (index = 0; list[index] != NULL; index++) + { + if (ch != message && list[index][0] == _T_ECLIPSE('-') && *(ch-1) == _T_ECLIPSE(' ')) + *(ch-1) = _T_ECLIPSE('\n'); + _tcscpy( ch, list[index] ); + ch += _tcslen( list[index] ); + *ch++ = _T_ECLIPSE(' '); + } + if(list == vmArgs) list = progArgs; + else list = NULL; + } + *ch = _T_ECLIPSE('\0'); + + return message; +} + +_TCHAR* getOfficialName() { + return officialName; +} + +void setOfficialName(_TCHAR* name) { + officialName = name; +} + +_TCHAR* getProgramPath() { + return program; +} + +void setProgramPath(_TCHAR* path) { + program = path; +} + +/* + * Determine the default official application name + * + * This function provides the default application name that appears in a variety of + * places such as: title of message dialog, title of splash screen window + * that shows up in Windows task bar. + * It is computed from the name of the launcher executable and + * by capitalizing the first letter. e.g. "c:/ide/eclipse.exe" provides + * a default name of "Eclipse". + */ +static _TCHAR* getDefaultOfficialName() +{ + _TCHAR *ch = NULL; + + /* Skip the directory part */ + ch = lastDirSeparator( program ); + if (ch == NULL) ch = program; + else ch++; + + ch = _tcsdup( ch ); +#ifdef _WIN32 + { + /* Search for the extension .exe and cut it */ + _TCHAR *extension = _tcsrchr(ch, _T_ECLIPSE('.')); + if (extension != NULL) + { + *extension = _T_ECLIPSE('\0'); + } + } +#endif + /* Upper case the first character */ +#ifndef LINUX + { + *ch = _totupper(*ch); + } +#else + { + if (*ch >= 'a' && *ch <= 'z') + { + *ch -= 32; + } + } +#endif + return ch; +} + +/* Determine the Program Directory + * + * This function takes the directory where program executable resides and + * determines the installation directory. + */ +_TCHAR* getProgramDir( ) +{ + _TCHAR* ch; + _TCHAR* programDir; + if (program == NULL) + return NULL; + programDir = malloc( (_tcslen( program ) + 1) * sizeof(_TCHAR) ); + _tcscpy( programDir, program ); + ch = lastDirSeparator( programDir ); + if (ch != NULL) + { + *(ch+1) = _T_ECLIPSE('\0'); + return programDir; + } + + free( programDir ); + return NULL; +} + +static _TCHAR* findSplash(_TCHAR* splashArg) { + struct _stat stats; + _TCHAR *ch; + _TCHAR *path, *prefix; + size_t length; + + if (splashArg == NULL) + return NULL; + + splashArg = _tcsdup(splashArg); + length = _tcslen(splashArg); + /* _tstat doesn't seem to like dirSeparators on the end */ + while (IS_DIR_SEPARATOR(splashArg[length - 1])) { + splashArg[--length] = 0; + } + + /* does splashArg exist */ + if (_tstat(splashArg, &stats) == 0) { + /* pointing to a file */ + if (stats.st_mode & S_IFREG) { + /* file, use it*/ + return splashArg; + } else if (stats.st_mode & S_IFDIR) { + /*directory, look for splash.bmp*/ + ch = malloc( (length + 12) * sizeof(_TCHAR)); + _stprintf( ch, _T_ECLIPSE("%s%c%s"), splashArg, dirSeparator, _T_ECLIPSE("splash.bmp") ); + if (_tstat(ch, &stats) == 0 && stats.st_mode & S_IFREG) { + free(splashArg); + return ch; + } + free(ch); + } + free(splashArg); + return NULL; + } + + /* doesn't exist, separate into path & prefix and look for a /path/prefix_<version> */ + ch = lastDirSeparator( splashArg ); + if (ch != NULL) { + if (IS_ABSOLUTE(splashArg)) + { /*absolute path*/ + path = _tcsdup(splashArg); + path[ch - splashArg] = 0; + } else { + /* relative path, prepend with programDir */ + path = malloc( (_tcslen(programDir) + ch - splashArg + 2) * sizeof(_TCHAR)); + *ch = 0; + _stprintf(path, _T_ECLIPSE("%s%c%s"), programDir, dirSeparator, splashArg); + *ch = dirSeparator; + } + prefix = _tcsdup(ch + 1); + } else { + /* No separator, treat splashArg as the prefix and look in the plugins dir */ + path = malloc( (_tcslen(programDir) + 9) * sizeof(_TCHAR)); + _stprintf(path, _T_ECLIPSE("%s%c%s"), programDir, dirSeparator, _T_ECLIPSE("plugins")); + prefix = _tcsdup(splashArg); + } + + ch = findFile(path, prefix); + free(path); + free(prefix); + free(splashArg); + if (ch != NULL) { + path = malloc((_tcslen(ch) + 12) * sizeof(_TCHAR)); + _stprintf( path, _T_ECLIPSE("%s%c%s"), ch, dirSeparator, _T_ECLIPSE("splash.bmp") ); + return path; + } + return NULL; +} + +static _TCHAR* findStartupJar(){ + _TCHAR * file, *ch; + _TCHAR * pluginsPath; + struct _stat stats; + size_t pathLength, progLength; + + if( startupArg != NULL ) { + /* startup jar was specified on the command line */ + ch = _tcsdup(startupArg); + /* check path will check relative paths against programDir and workingDir */ + file = checkPath(ch, programDir, 1); + if(file != ch) + free(ch); + /* check existence */ + if (_tstat( file, &stats ) != 0) { + free(file); + file = NULL; + } + return file; + } + + progLength = pathLength = _tcslen(programDir); +#ifdef MACOSX + pathLength += 9; +#endif + pluginsPath = malloc( (pathLength + 1 + 7 + 1) * sizeof(_TCHAR)); + _tcscpy(pluginsPath, programDir); + if(!IS_DIR_SEPARATOR(pluginsPath[progLength - 1])) { + pluginsPath[progLength] = dirSeparator; + pluginsPath[progLength + 1] = 0; + } +#ifdef MACOSX + _tcscat(pluginsPath, _T_ECLIPSE("../../../")); +#endif + _tcscat(pluginsPath, _T_ECLIPSE("plugins")); + + /* equinox startup jar? */ + file = findFile(pluginsPath, DEFAULT_EQUINOX_STARTUP); + if(file != NULL) + return file; + + /* old startup.jar? */ + ch = OLD_STARTUP; + file = checkPath(ch, programDir, 1); + if (_tstat( file, &stats ) == 0) + return (file == ch) ? _tcsdup(ch) : file; + + return NULL; +} + +/* + * Return the portion of the vmCommand that should be used for relaunching + * + * The memory allocated for the command array must be freed + */ +static _TCHAR ** getRelaunchCommand( _TCHAR **vmCommand ) +{ + int i = -1, req = 0, begin = -1; + int idx = 0; + _TCHAR ** relaunch; + + if (vmCommand == NULL) return NULL; + while(vmCommand[++i] != NULL){ + if ( begin == -1 && _tcsicmp( vmCommand[i], *reqVMarg[req] ) == 0) { + if(reqVMarg[++req] == NULL || *reqVMarg[req] == NULL){ + begin = i + 1; + } + } + } + + relaunch = malloc((1 + i + 1) * sizeof(_TCHAR *)); + relaunch[idx++] = program; + if(begin == -1) { + begin = 1; + } + for (i = begin; vmCommand[i] != NULL; i++){ + if (_tcsicmp(vmCommand[i], SHOWSPLASH) == 0) { + /* remove if the next argument is not the bitmap to show */ + if(vmCommand[i + 1] != NULL && vmCommand[i + 1][0] == _T_ECLIPSE('-')) { + continue; + } + } else if(_tcsncmp(vmCommand[i], CLASSPATH_PREFIX, _tcslen(CLASSPATH_PREFIX)) == 0) { + /* skip -Djava.class.path=... */ + continue; + } + relaunch[idx++] = vmCommand[i]; + } + if(_tcsicmp(relaunch[idx - 1], VMARGS) == 0) + relaunch[idx - 1] = NULL; + relaunch[idx] = NULL; + return relaunch; +} + +#ifdef _WIN32 +static void createConsole() { +#ifndef WIN64 +#define intptr_t long +#endif + intptr_t stdHandle; + int conHandle; + FILE *fp; + + AllocConsole(); + + /* redirect stdout */ + stdHandle = (intptr_t) GetStdHandle(STD_OUTPUT_HANDLE); + conHandle = _open_osfhandle(stdHandle, _O_TEXT); + if (conHandle != -1) { + fp = _fdopen(conHandle, "w"); + *stdout = *fp; + } + + /* redirect stdin */ + stdHandle = (intptr_t) GetStdHandle(STD_INPUT_HANDLE); + conHandle = _open_osfhandle(stdHandle, _O_TEXT); + if (conHandle != -1) { + fp = _fdopen(conHandle, "r"); + *stdin = *fp; + } + + /* stderr */ + stdHandle = (intptr_t) GetStdHandle(STD_ERROR_HANDLE); + conHandle = _open_osfhandle(stdHandle, _O_TEXT); + if (conHandle != -1) { + fp = _fdopen(conHandle, "r"); + *stderr = *fp; + } +} + +/* Determine if the launcher was the eclipsec.exe or not based on whether we have an attached console. + * This will only be correct if called before createConsole. + */ +static int isConsoleLauncher() { + HWND (WINAPI *GetConsoleWindow)(); + void * handle = loadLibrary(_T_ECLIPSE("Kernel32.dll")); + if (handle != NULL) { + if ( (GetConsoleWindow = findSymbol(handle, _T_ECLIPSE("GetConsoleWindow"))) != NULL) { + return GetConsoleWindow() != NULL; + } + } + return 0; +} + +static void fixDLLSearchPath() { +#ifdef UNICODE + _TCHAR* functionName = _T_ECLIPSE("SetDllDirectoryW"); +#else + _TCHAR* functionName = _T_ECLIPSE("SetDllDirectoryA"); +#endif + + BOOL (WINAPI *SetDLLDirectory)(LPCTSTR); + void * handle = loadLibrary(_T_ECLIPSE("Kernel32.dll")); + if (handle != NULL) { + if ( (SetDLLDirectory = findSymbol(handle, functionName)) != NULL) { + SetDLLDirectory(_T_ECLIPSE("")); + } + } +} + +#endif + +/* Set the vm to use based on the given .ee file. + */ +static int vmEEProps(_TCHAR * eeFile, _TCHAR ** msg) { + if (processEEProps(eeFile) != 0) { + *msg = _tcsdup(eeFile); + return -1; + } + if (eeLibrary != NULL) { + jniLib = findVMLibrary(eeLibrary); + if (jniLib != NULL) + return LAUNCH_JNI; + } + + if (eeConsole != NULL && (debug || needConsole || consoleLauncher) ) { + javaVM = findSymlinkCommand(eeConsole, 0); + if (javaVM != NULL) + return LAUNCH_EXE; + } + + if (eeExecutable != NULL) { + javaVM = findSymlinkCommand(eeExecutable, 0); + if (javaVM != NULL) + return LAUNCH_EXE; + } + + *msg = _tcsdup(eeFile); + return -1; +} + +/* + * determine the vm to use. + * return LAUNCH_JNI for launching with JNI invocation API. jniLib contains the name of the library + * returh LAUNCH_EXE for execing java, javaVM contains the path to the exe + * return -1 if problem finding vm, the passed in msg points to the places we looked. Caller should free + * this memory. + */ +static int determineVM(_TCHAR** msg) { + _TCHAR* ch = NULL; + _TCHAR* result = NULL; + _TCHAR* vmSearchPath = NULL; + _TCHAR* defaultJava = defaultVM; /* default exe to look for */ + int type = 0; + +#ifdef _WIN32 + if (debug || needConsole || consoleLauncher) + defaultJava = consoleVM; /* windows will want java.exe for the console, not javaw.exe */ +#endif + + /* vmName is passed in on command line with -vm */ + if (vmName != NULL) { + size_t length = _tcslen(vmName); + /* remove the trailing separator */ + if (vmName[length - 1] == _T_ECLIPSE('/') || vmName[length - 1] == _T_ECLIPSE('\\')) { + vmName[length - 1] = 0; + } + + vmName = checkPath(vmName, programDir, 1); + type = checkProvidedVMType(vmName); + switch (type) { + case VM_DIRECTORY: + /* vmName is a directory, look for default.ee */ + ch = malloc((_tcslen(vmName) + 1 + _tcslen(DEFAULT_EE) + 1) * sizeof(_TCHAR)); + _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, DEFAULT_EE ); + + result = findCommand(ch); + free(ch); + if (result == NULL) { + /* No default.ee file, look for default VM */ + ch = malloc((_tcslen(vmName) + 1 + _tcslen(defaultJava) + 1) * sizeof(_TCHAR)); + _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, defaultJava ); + javaVM = findSymlinkCommand(ch, 0); + free(ch); + if (javaVM == NULL) { + /* No vm executable, look for library */ + ch = malloc((_tcslen(vmName) + 1 + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); + _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, vmLibrary ); + jniLib = findVMLibrary(ch); + if (jniLib != ch) + free(ch); + if (jniLib != NULL) { + return LAUNCH_JNI; + } + /* found nothing, return error */ + *msg = malloc( (3 * (_tcslen(vmName) + 2) + _tcslen(DEFAULT_EE) + _tcslen(defaultJava) + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); + _stprintf( *msg, _T_ECLIPSE("%s%c%s\n%s%c%s\n%s%c%s"), vmName, dirSeparator, DEFAULT_EE, + vmName, dirSeparator, defaultJava, + vmName, dirSeparator, vmLibrary); + return -1; + } + break; + } + + /* else default.ee does exist */ + vmName = result; + /* fall through to VM_EE_PROPS*/ + case VM_EE_PROPS: + return vmEEProps(vmName, msg); + + case VM_LIBRARY: + ch = findCommand(vmName); + if(ch != NULL) { + jniLib = findVMLibrary(ch); + if (ch != jniLib) + free(ch); + return LAUNCH_JNI; + } + /* file didn't exist, error */ + if (firstDirSeparator( vmName ) == NULL) { + /* if vmName doesn't contain a dirSeparator, we looked on the path */ + *msg = malloc((_tcslen(pathMsg) + _tcslen(vmName)) * sizeof(_TCHAR)); + _stprintf( *msg, pathMsg,vmName ); + } else { + *msg = _tcsdup(vmName); + } + return -1; + + default: + /*otherwise, assume executable */ + javaVM = findSymlinkCommand(vmName, 0); + if(javaVM != NULL) { +#ifdef MACOSX + /* right now, we are always doing JNI on Mac */ + break; +#else + return LAUNCH_EXE; +#endif + } + /* file didn't exist, error */ + if (firstDirSeparator( vmName ) == NULL) { + /* if vmName doesn't contain a dirSeparator, we looked on the path */ + *msg = malloc((_tcslen(pathMsg) + _tcslen(vmName)) * sizeof(_TCHAR)); + _stprintf( *msg, pathMsg, vmName ); + } else { + *msg = _tcsdup(vmName); + } + return -1; + } + } + + if (vmName == NULL) { + /* no vm specified, Try to find the VM shipped with eclipse. */ + + /* look first for default.ee */ + ch = malloc( (_tcslen( programDir ) + _tcslen( shippedVMDir ) + _tcslen( DEFAULT_EE ) + 1) * sizeof(_TCHAR) ); + _stprintf( ch, _T_ECLIPSE("%s%s%s"), programDir, shippedVMDir, DEFAULT_EE ); + result = findCommand(ch); + free(ch); + if (result != NULL) { + type = vmEEProps(result, msg); + free(result); + return type; + } + + /* then look for java(w).exe */ + ch = malloc( (_tcslen( programDir ) + _tcslen( shippedVMDir ) + _tcslen( defaultJava ) + 10) * sizeof(_TCHAR) ); + _stprintf( ch, _T_ECLIPSE("%s%s%s"), programDir, shippedVMDir, defaultJava ); + vmSearchPath = _tcsdup(ch); + + javaVM = findSymlinkCommand( ch, 0 ); + free(ch); + } + + if (javaVM == NULL) { + /* vm not found yet, look for one on the search path, but don't resolve symlinks */ + javaVM = findSymlinkCommand(defaultJava, 0); + if (javaVM == NULL) { + /* can't find vm, error */ + ch = malloc( (_tcslen(pathMsg) + _tcslen(defaultJava) + 1) * sizeof(_TCHAR)); + _stprintf(ch, pathMsg, defaultJava); + + if(vmSearchPath != NULL) { + *msg = malloc((_tcslen(ch) + 1 + _tcslen(vmSearchPath) + 1) * sizeof(_TCHAR)); + _stprintf(*msg, _T_ECLIPSE("%s\n%s"), vmSearchPath, ch); + free(ch); + } else { + *msg = ch; + } + return -1; + } + } + + if (vmSearchPath != NULL) + free(vmSearchPath); + +#ifndef DEFAULT_JAVA_EXEC + /* resolve symlinks for finding the library */ + ch = resolveSymlinks(javaVM); + jniLib = findVMLibrary(ch); + if (ch != jniLib && ch != javaVM) + free(ch); + if (jniLib != NULL) + return LAUNCH_JNI; +#endif + + return LAUNCH_EXE; +} + +static int processEEProps(_TCHAR* eeFile) +{ + _TCHAR ** argv; + _TCHAR * c1, * c2; + _TCHAR * eeDir; + int argc; + int index, i; + int matches = 0; + Option *option; + + if(readConfigFile(eeFile, &argc, &argv) != 0) + return -1; + + nEEargs = argc; + eeVMarg = argv; + + eeDir = _tcsdup(eeFile); + c1 = lastDirSeparator( eeDir ); + while (c1 != NULL) + { + *c1 = _T_ECLIPSE('\0'); + c1--; /* IS_DIR_SEPARATOR evalutes c twice, decrement out here */ + if (!IS_DIR_SEPARATOR(*c1)) + c1 = NULL; + } + + for (index = 0; index < argc; index++){ + /* replace ${ee.home} with eeDir, loop in case there is more than one per argument */ + while( (c1 = _tcsstr(argv[index], EE_HOME_VAR)) != NULL) + { + /* the space needed for c1 is included in _tcslen(argv[index]) */ + c2 = malloc( (_tcslen(argv[index]) + _tcslen(eeDir) + 1) * sizeof(_TCHAR)); + *c1 = _T_ECLIPSE('\0'); + _stprintf(c2, _T_ECLIPSE("%s%s%s"), argv[index], eeDir, c1 + 10); /* ${ee.home} is 10 characters */ + free(argv[index]); + argv[index] = c2; + } + + /* Find the corresponding argument is a option supported by the launcher */ + option = NULL; + for (i = 0; option == NULL && i < eeOptionsSize; i++) + { + if (_tcsncmp( argv[index], eeOptions[i].name, _tcslen(eeOptions[i].name) ) == 0) { + option = &eeOptions[i]; + break; + } + } + if(option != NULL) { + ++matches; + if (option->flag & VALUE_IS_FLAG) + *((int*)option->value) = 1; + else { + c1 = malloc( (_tcslen(argv[index]) - _tcslen(option->name) + 1) *sizeof(_TCHAR)); + _tcscpy(c1, argv[index] + _tcslen(option->name)); + if (option->flag & ADJUST_PATH && option->flag & VALUE_IS_LIST) { + c2 = checkPathList(c1, eeDir, 1); + free(c1); + c1 = c2; + } else if (option->flag & ADJUST_PATH) { + c2 = checkPath(c1, eeDir, 1); + if (c2 != c1) { + free(c1); + c1 = c2; + } + } + *((_TCHAR**)option->value) = c1; + } + if(matches == eeOptionsSize) + break; + } + } + /* set ee.home, ee.filename variables, and NULL */ + argv = realloc(argv, (nEEargs + 3) * sizeof(_TCHAR*)); + + c1 = malloc( (_tcslen(EE_HOME) + _tcslen(eeDir) + 1) * sizeof(_TCHAR)); + _stprintf(c1, _T_ECLIPSE("%s%s"), EE_HOME, eeDir); + argv[nEEargs++] = c1; + + c1 = malloc( (_tcslen(EE_FILENAME) + _tcslen(eeFile) + 1) * sizeof(_TCHAR)); + _stprintf(c1, _T_ECLIPSE("%s%s"), EE_FILENAME, eeFile); + argv[nEEargs++] = c1; + + argv[nEEargs] = NULL; + + free(eeDir); + return 0; +} + +/* returns an array of paths that should be place on the search path for loading + * the vm shared libraries. + * Each entry is terminated with the platform path separator. + * Entries are either from the ee.library.path or calculated from the path to the + * vm shared library itself. + */ +_TCHAR ** getVMLibrarySearchPath(_TCHAR * vmLibrary) { + _TCHAR ** paths = NULL; + _TCHAR * buffer = NULL; + _TCHAR * path, * entry, *c; + _TCHAR separator; + int numPaths = 3; + int i; + struct _stat stats; + + buffer = (eeLibPath != NULL) ? _tcsdup(eeLibPath) : _tcsdup(vmLibrary); +#ifdef WIN32 + /* On windows we sometimes get '/' instead of '\', just always use '/' */ + i = -1; + while (buffer[++i] != 0) { + if (buffer[i] == _T_ECLIPSE('\\')) + buffer[i] = _T_ECLIPSE('/'); + } +#endif + + separator = (eeLibPath != NULL) ? pathSeparator : _T_ECLIPSE('/'); + + if (eeLibPath != NULL) { + /* count number of path elements */ + numPaths = 1; + c = eeLibPath; + while( (c = _tcschr(c, pathSeparator)) != NULL) { + numPaths++; + c++; + } + } + + paths = malloc((numPaths + 1) * sizeof(_TCHAR*)); + paths[numPaths] = NULL; + + /* We are either splitting eeLibPath (eg path1:path2), or we are extracting + * from libPath where we want the directory containing the library and the + * parent directory of that, and also grandparent/lib/arch */ + for (i = 0; i < numPaths; i++) { + c = _tcsrchr(buffer, separator); + if (c != 0) { + *c++ = 0; + if (eeLibPath != NULL) { + path = c; /* we want from c to the end */ + } else { + path = buffer; /* we want from the start to c */ + } + } else { + if (eeLibPath != NULL) { + path = buffer; + } else { + paths[i] = NULL; + break; + } + } + if (path != NULL) { + entry = resolveSymlinks(path); /* this may be a new string */ + if (eeLibPath == NULL && i == 2) { + /* trying grandparent/lib/arch */ + const _TCHAR * arch = getVMArch(); + paths[i] = malloc((_tcslen(entry) + 7 + _tcslen(arch)) * sizeof(_TCHAR)); + _stprintf(paths[i], _T_ECLIPSE("%s/lib/%s"), entry, arch); + /* only add if the path actually exists */ + if (_tstat(paths[i], &stats) == 0) { + _TCHAR separatorString[] = { pathSeparator, 0 }; + _tcscat(paths[i], separatorString); + } else { + free(paths[i]); + paths[i] = NULL; + } + } else { + paths[i] = malloc((_tcslen(entry) + 2) * sizeof(_TCHAR)); + _stprintf( paths[i], _T_ECLIPSE("%s%c"), entry, pathSeparator ); + } + if (entry != path) + free(entry); + path = NULL; + } + } + + free(buffer); + return paths; +} + +/* translate the osArchArg into the value that we expect the jre to use */ +const _TCHAR* getVMArch() { + if (_tcscmp(osArchArg, _T_ECLIPSE("x86_64")) == 0) + return _T_ECLIPSE("amd64"); + else if (_tcscmp(osArchArg, _T_ECLIPSE("x86")) == 0) + return _T_ECLIPSE("i386"); + else + return osArchArg; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c new file mode 100644 index 000000000..923b3c22e --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c @@ -0,0 +1,570 @@ +/******************************************************************************* + * Copyright (c) 2006, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + * Martin Oberhuber (Wind River) - [176805] Support Solaris9 by adding setenv() + *******************************************************************************/ + +#include "eclipseCommon.h" +#include "eclipseUnicode.h" + +#ifdef _WIN32 +#include <direct.h> +#include <windows.h> +#else +#include <unistd.h> +#include <string.h> +#include <dirent.h> +#include <limits.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <errno.h> + +/* Global Variables */ +_TCHAR* osArg = _T_ECLIPSE(DEFAULT_OS); +#ifdef MACOSX + /* on the mac we have a universal binary, decide ppc vs x86 based on endianness */ + #ifdef __BIG_ENDIAN__ + _TCHAR* osArchArg = _T_ECLIPSE("ppc"); + #else + _TCHAR* osArchArg = _T_ECLIPSE(DEFAULT_OS_ARCH); + #endif +#else +_TCHAR* osArchArg = _T_ECLIPSE(DEFAULT_OS_ARCH); +#endif +_TCHAR* wsArg = _T_ECLIPSE(DEFAULT_WS); /* the SWT supported GUI to be used */ + +/* Local Variables */ +static _TCHAR* filterPrefix = NULL; /* prefix for the find files filter */ +static size_t prefixLength = 0; + +static int isFolder(const _TCHAR* path, const _TCHAR* entry); + +typedef struct { + int segment[3]; + _TCHAR * qualifier; +} Version; + +static void freeVersion(Version *version) +{ + if(version->qualifier) + free(version->qualifier); + free(version); +} + +static Version* parseVersion(const _TCHAR * str) { + _TCHAR *copy; + _TCHAR *c1, *c2 = NULL; + int i = 0; + + Version *version = malloc(sizeof(Version)); + memset(version, 0, sizeof(Version)); + + c1 = copy = _tcsdup(str); + while (c1 && *c1 != 0) + { + if (i < 3) { + version->segment[i] = (int)_tcstol(c1, &c2, 10); + /* if the next character is not '.', then we couldn't + * parse as a int, the remainder is not valid (or we are at the end)*/ + if (*c2 && *c2 != _T_ECLIPSE('.')) + break; + c2++; /* increment past the . */ + } else { + c2 = _tcschr(c1, _T_ECLIPSE('.')); + if(c2 != NULL) { + *c2 = 0; + version->qualifier = _tcsdup(c1); + *c2 = _T_ECLIPSE('.'); /* put the dot back */ + } else { + if(_tcsicmp(c1, _T_ECLIPSE("jar")) == 0) + version->qualifier = 0; + else + version->qualifier = _tcsdup(c1); + } + break; + } + c1 = c2; + i++; + } + free(copy); + return version; +} + +static int compareVersions(const _TCHAR* str1, const _TCHAR* str2) { + int result = 0, i = 0; + Version *v1 = parseVersion(str1); + Version *v2 = parseVersion(str2); + + while (result == 0 && i < 3) { + result = v1->segment[i] - v2->segment[i]; + i++; + } + if(result == 0) { + _TCHAR * q1 = v1->qualifier ? v1->qualifier : _T_ECLIPSE(""); + _TCHAR * q2 = v2->qualifier ? v2->qualifier : _T_ECLIPSE(""); + result = _tcscmp(q1, q2); + } + + freeVersion(v1); + freeVersion(v2); + return result; +} + +/** + * Convert a wide string to a narrow one + * Caller must free the null terminated string returned. + */ +char *toNarrow(const _TCHAR* src) +{ +#ifdef UNICODE + int byteCount = WideCharToMultiByte (CP_ACP, 0, (wchar_t *)src, -1, NULL, 0, NULL, NULL); + char *dest = malloc(byteCount+1); + dest[byteCount] = 0; + WideCharToMultiByte (CP_ACP, 0, (wchar_t *)src, -1, dest, byteCount, NULL, NULL); + return dest; +#else + return (char*)_tcsdup(src); +#endif +} + + +/** + * Set an environment variable. + * Solaris versions <= Solaris 9 did not know setenv in libc, + * so emulate it here. + */ +#if defined(SOLARIS) || defined(HPUX) +int setenv (const char *name, const char *value, int replace) +{ + int namelen, valuelen, rc; + char *var; + if (replace == 0) { + const char *oldval = getenv(name); + if (oldval != NULL) { + return 0; + } + } + namelen = strlen(name); + valuelen = strlen(value); + var = malloc( (namelen + valuelen + 2) * sizeof(char) ); + if (var == NULL) { + return -1; + } + /* Use strncpy as protection, in case a thread modifies var + * after we obtained its length */ + strncpy(var, name, namelen); + var[namelen] = '='; + strncpy( &var[namelen + 1], value, valuelen); + var[namelen + valuelen + 1] = '\0'; + rc = putenv(var); + if (rc != 0) rc = -1; /*putenv returns non-zero on error; setenv -1*/ + return rc; +} +#endif + + /* + * Find the absolute pathname to where a command resides. + * + * The string returned by the function must be freed. + */ +#define EXTRA 20 +_TCHAR* findCommand( _TCHAR* command ) +{ + return findSymlinkCommand( command, 1 ); +} + +_TCHAR* findSymlinkCommand( _TCHAR* command, int resolve ) +{ + _TCHAR* cmdPath; + size_t length; + _TCHAR* ch; + _TCHAR* dir; + _TCHAR* path; + struct _stat stats; + + /* If the command was an abolute pathname, use it as is. */ + if (IS_ABSOLUTE(command)) + { + length = _tcslen( command ); + cmdPath = malloc( (length + EXTRA) * sizeof(_TCHAR) ); /* add extra space for a possible ".exe" extension */ + _tcscpy( cmdPath, command ); + } + + else + { + /* If the command string contains a path separator */ + if (firstDirSeparator( command ) != NULL) + { + /* It must be relative to the current directory. */ + length = MAX_PATH_LENGTH + EXTRA + _tcslen( command ); + cmdPath = malloc( length * sizeof (_TCHAR)); + _tgetcwd( cmdPath, length ); + length = _tcslen(cmdPath); + if (!IS_DIR_SEPARATOR(cmdPath[ length - 1 ])) + { + cmdPath[ length ] = dirSeparator; + cmdPath[ length+1 ] = _T_ECLIPSE('\0'); + } + _tcscat( cmdPath, command ); + } + + /* else the command must be in the PATH somewhere */ + else + { + /* Get the directory PATH where executables reside. */ + path = _tgetenv( _T_ECLIPSE("PATH") ); +#ifdef _WIN32 + /* on windows, prepend the current directory */ + if (path == NULL) + path = _T_ECLIPSE(""); + ch = malloc((_tcslen(path) + MAX_PATH_LENGTH + 2) * sizeof(_TCHAR)); + _tgetcwd( ch, MAX_PATH_LENGTH ); + length = _tcslen(ch); + ch[length] = pathSeparator; + _tcscpy(&ch[length + 1], path); + path = ch; +#endif + if (!path) + { + return NULL; + } + else + { + length = _tcslen( path ) + _tcslen( command ) + MAX_PATH_LENGTH; + cmdPath = malloc( length * sizeof(_TCHAR)); + + /* Foreach directory in the PATH */ + dir = path; + while (dir != NULL && *dir != _T_ECLIPSE('\0')) + { + ch = _tcschr( dir, pathSeparator ); + if (ch == NULL) + { + _tcscpy( cmdPath, dir ); + } + else + { + length = ch - dir; + _tcsncpy( cmdPath, dir, length ); + cmdPath[ length ] = _T_ECLIPSE('\0'); + ch++; + } + dir = ch; /* advance for the next iteration */ + +#ifdef _WIN32 + /* Remove quotes */ + if (_tcschr( cmdPath, _T_ECLIPSE('"') ) != NULL) + { + size_t i = 0, j = 0; + _TCHAR c; + length = _tcslen( cmdPath ); + while (i < length) { + c = cmdPath[ i++ ]; + if (c == _T_ECLIPSE('"')) continue; + cmdPath[ j++ ] = c; + } + cmdPath[ j ] = _T_ECLIPSE('\0'); + } +#endif + /* Determine if the executable resides in this directory. */ + if (_tcslen(cmdPath) == 0 || /*an empty path entry is treated as '.' */ + (cmdPath[0] == _T_ECLIPSE('.') && (_tcslen(cmdPath) == 1 || (_tcslen(cmdPath) == 2 && IS_DIR_SEPARATOR(cmdPath[1]))))) + { + _tgetcwd( cmdPath, MAX_PATH_LENGTH ); + } + length = _tcslen(cmdPath); + if (!IS_DIR_SEPARATOR(cmdPath[ length - 1 ])) + { + cmdPath[ length ] = dirSeparator; + cmdPath[ length+1 ] = _T_ECLIPSE('\0'); + } + _tcscat( cmdPath, command ); + + /* If the file is not a directory and can be executed */ + if (_tstat( cmdPath, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { + /* Stop searching */ + dir = NULL; + } + } + } + } + } + +#ifdef _WIN32 + /* If the command does not exist */ + if (_tstat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0) + { + /* If the command does not end with .exe, append it an try again. */ + length = _tcslen( cmdPath ); + if (length > 4 && _tcsicmp( &cmdPath[ length - 4 ], _T_ECLIPSE(".exe") ) != 0) + _tcscat( cmdPath, _T_ECLIPSE(".exe") ); + } +#endif + + /* Verify the resulting command actually exists. */ + if (_tstat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0) + { + free( cmdPath ); + cmdPath = NULL; + return cmdPath; + } + + if (resolve) { + ch = resolveSymlinks(cmdPath); + if (ch != cmdPath) { + free(cmdPath); + cmdPath = ch; + } + } + return cmdPath; +} + +#if !defined(_WIN32) && !defined(MACOSX) +char * resolveSymlinks( char * path ) { + char * ch, *buffer; + if(path == NULL) + return path; + /* resolve symlinks */ + ch = path; + buffer = malloc(PATH_MAX); + path = realpath(path, buffer); + if (path != buffer) + free(buffer); + if (path == NULL) + return ch; /* failed to resolve the links, return original path */ + return path; +} +#endif + +#ifdef _WIN32 +static int filter(_TCHAR* candidate, int isFolder) { +#else +#ifdef MACOSX +static int filter(struct dirent *dir, int isFolder) { +#else +static int filter(const struct dirent *dir, int isFolder) { +#endif + char * candidate = (char *)dir->d_name; +#endif + _TCHAR *lastDot, *lastUnderscore; + int result; + + if(_tcslen(candidate) <= prefixLength) + return 0; + if (_tcsncmp(candidate, filterPrefix, prefixLength) != 0 || candidate[prefixLength] != _T_ECLIPSE('_')) + return 0; + + candidate = _tcsdup(candidate); + + /* remove trailing .jar and .zip extensions, leave other extensions because we need the '.' */ + lastDot = _tcsrchr(candidate, _T_ECLIPSE('.')); + if (!isFolder && lastDot != NULL && (_tcscmp(lastDot, _T_ECLIPSE(".jar")) == 0 || _tcscmp(lastDot, _T_ECLIPSE(".zip")) == 0)) { + *lastDot = 0; + lastDot = _tcsrchr(candidate, _T_ECLIPSE('.')); + } + + if (lastDot < &candidate[prefixLength]) { + free(candidate); + return 0; + } + + lastUnderscore = _tcsrchr(candidate, _T_ECLIPSE('_')); + + /* get past all the '_' that are part of the qualifier */ + while(lastUnderscore > lastDot) { + *lastUnderscore = 0; + lastUnderscore = _tcsrchr(candidate, _T_ECLIPSE('_')); + } + /* is this the underscore at the end of the prefix? */ + result = (lastUnderscore == &candidate[prefixLength]); + free(candidate); + return result; +} + + /* + * Looks for files of the form /path/prefix_version.<extension> and returns the full path to + * the file with the largest version number + */ +_TCHAR* findFile( _TCHAR* path, _TCHAR* prefix) +{ + struct _stat stats; + size_t pathLength; + _TCHAR* candidate = NULL; + _TCHAR* result = NULL; + +#ifdef _WIN32 + _TCHAR* fileName = NULL; + WIN32_FIND_DATA data; + HANDLE handle; +#else + DIR *dir = NULL; + struct dirent * entry = NULL; +#endif + + path = _tcsdup(path); + pathLength = _tcslen(path); + + /* strip dirSeparators off the end */ + while (IS_DIR_SEPARATOR(path[pathLength - 1])) { + path[--pathLength] = 0; + } + + /* does path exist? */ + if( _tstat(path, &stats) != 0 ) { + free(path); + return NULL; + } + + filterPrefix = prefix; + prefixLength = _tcslen(prefix); +#ifdef _WIN32 + fileName = malloc( (_tcslen(path) + 1 + _tcslen(prefix) + 3) * sizeof(_TCHAR)); + _stprintf(fileName, _T_ECLIPSE("%s%c%s_*"), path, dirSeparator, prefix); + + handle = FindFirstFile(fileName, &data); + if(handle != INVALID_HANDLE_VALUE) { + if (filter(data.cFileName, isFolder(path, data.cFileName))) + candidate = _tcsdup(data.cFileName); + while(FindNextFile(handle, &data) != 0) { + if (filter(data.cFileName, isFolder(path, data.cFileName))) { + if (candidate == NULL) { + candidate = _tcsdup(data.cFileName); + } else if( compareVersions(candidate + prefixLength + 1, data.cFileName + prefixLength + 1) < 0) { + /* compare, take the highest version */ + free(candidate); + candidate = _tcsdup(data.cFileName); + } + } + } + FindClose(handle); + } +#else + if ((dir = opendir(path)) == NULL) { + free(path); + return NULL; + } + + while ((entry = readdir(dir)) != NULL) { + if (filter(entry, isFolder(path, entry->d_name))) { + if (candidate == NULL) { + candidate = _tcsdup(entry->d_name); + } else if (compareVersions(candidate + prefixLength + 1, entry->d_name + prefixLength + 1) < 0) { + free(candidate); + candidate = _tcsdup(entry->d_name); + } + } + } + closedir(dir); +#endif + + if(candidate != NULL) { + result = malloc((pathLength + 1 + _tcslen(candidate) + 1) * sizeof(_TCHAR)); + _tcscpy(result, path); + result[pathLength] = dirSeparator; + result[pathLength + 1] = 0; + _tcscat(result, candidate); + free(candidate); + } + free(path); + return result; +} + +int isFolder(const _TCHAR* path, const _TCHAR* entry) { + int result = 0; + struct _stat stats; + _TCHAR * fullPath = malloc((_tcslen(path) + _tcslen(entry) + 2) * sizeof(_TCHAR)); + _stprintf(fullPath, _T_ECLIPSE("%s%c%s"), path, dirSeparator, entry); + + result = _tstat(fullPath, &stats); + free(fullPath); + return (result == 0 && (stats.st_mode & S_IFDIR) != 0); +} + +/* + * If path is relative, attempt to make it absolute by + * 1) check relative to working directory + * 2) check relative to provided programDir + * If reverseOrder, then check the programDir before the working dir + */ +_TCHAR* checkPath( _TCHAR* path, _TCHAR* programDir, int reverseOrder ) +{ + int cwdLength = MAX_PATH_LENGTH; + int i; + _TCHAR * workingDir, * buffer, * result = NULL; + _TCHAR * paths[2]; + struct _stat stats; + + /* If the command was an abolute pathname, use it as is. */ + if (IS_ABSOLUTE(path)) { + return path; + } + + /* get the current working directory */ + workingDir = malloc(cwdLength * sizeof(_TCHAR)); + while ( _tgetcwd( workingDir, cwdLength ) == NULL ){ + if (errno == ERANGE) { + /* ERANGE : the buffer isn't big enough, allocate more memory */ + cwdLength *= 2; + workingDir = realloc(workingDir, cwdLength * sizeof(_TCHAR)); + continue; + } else { + /* some other error occurred, perhaps ENOENT (directory has been unlinked) */ + /* the contents of workingDir are undefined, set it to empty, we will end up testing against root */ + workingDir[0] = _T_ECLIPSE('\0'); + break; + } + } + + paths[0] = reverseOrder ? programDir : workingDir; + paths[1] = reverseOrder ? workingDir : programDir; + + /* just make a buffer big enough to hold everything */ + buffer = malloc((_tcslen(paths[0]) + _tcslen(paths[1]) + _tcslen(path) + 2) * sizeof(_TCHAR)); + for ( i = 0; i < 2; i++ ) { + if (_tcslen(paths[i]) == 0) + continue; + _stprintf(buffer, _T_ECLIPSE("%s%c%s"), paths[i], dirSeparator, path); + if (_tstat(buffer, &stats) == 0) { + result = _tcsdup(buffer); + break; + } + } + + free(buffer); + free(workingDir); + + /* if we found something, return it, otherwise, return the original */ + return result != NULL ? result : path; +} + +_TCHAR * lastDirSeparator(_TCHAR* str) { +#ifndef _WIN32 + return _tcsrchr(str, dirSeparator); +#else + int i = -1; + _TCHAR * c = NULL; + while (str[++i] != 0) { + if (str[i] == _T_ECLIPSE('\\') || str[i] == _T_ECLIPSE('/')) + c = &str[i]; + } + return c; +#endif +} + +_TCHAR * firstDirSeparator(_TCHAR* str) { +#ifdef _WIN32 + return _tcspbrk(str, _T_ECLIPSE("\\/")); +#else + return _tcschr(str, dirSeparator); +#endif +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h new file mode 100644 index 000000000..655f90122 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#ifndef ECLIPSE_COMMON_H +#define ECLIPSE_COMMON_H + +#include "eclipseUnicode.h" + +/* Variables and Methods that will be needed by both the executable and the library */ + +#define MAX_PATH_LENGTH 2000 + +#ifdef UNICODE +#define run runW +#define setInitialArgs setInitialArgsW +#define RUN_METHOD _T_ECLIPSE("runW") +#define SET_INITIAL_ARGS _T_ECLIPSE("setInitialArgsW") +#else +#define RUN_METHOD _T_ECLIPSE("run") +#define SET_INITIAL_ARGS _T_ECLIPSE("setInitialArgs") +#endif + +#define DEFAULT_EQUINOX_STARTUP _T_ECLIPSE("org.eclipse.equinox.launcher") + +#ifdef _WIN32 +#define IS_ABSOLUTE(path) (path[0] == _T_ECLIPSE('/') || path[0] == _T_ECLIPSE('\\') || (path[0] != 0 && path[1] == _T_ECLIPSE(':'))) +#define IS_DIR_SEPARATOR(c) (c == _T_ECLIPSE('/') || c == _T_ECLIPSE('\\')) +#else +#define IS_ABSOLUTE(path) (path[0] == dirSeparator) +#define IS_DIR_SEPARATOR(c) (c == dirSeparator) +#endif + +extern _TCHAR* osArg; +extern _TCHAR* osArchArg; +extern _TCHAR* wsArg; + +extern _TCHAR dirSeparator; /* '/' or '\\' */ +extern _TCHAR pathSeparator; /* separator used in PATH variable */ +extern _TCHAR* eclipseLibrary; /* path the the eclipse_<ver>.so shared library */ + +extern char *toNarrow(const _TCHAR* src); + + /* + * Find the absolute pathname to where a command resides. + * + * The string returned by the function must be freed. + * Symlinks are resolved + */ +extern _TCHAR* findCommand( _TCHAR* command ); + +/* + * Same as findCommand but optionally resolve symlinks + */ +extern _TCHAR* findSymlinkCommand( _TCHAR* command, int resolve ); + +extern _TCHAR* findFile( _TCHAR* path, _TCHAR* prefix); + +extern _TCHAR* getProgramDir(); + +extern _TCHAR* getOfficialName(); + +extern void setOfficialName(_TCHAR * name); + +extern _TCHAR* getProgramPath(); + +extern void setProgramPath(_TCHAR* name); + +extern _TCHAR* resolveSymlinks( _TCHAR* path ); + +/** Display a Message + * + * This method is called to display an error message to the user before exiting. + * The method should not return until the user has acknowledged + * the message. This method may be called before the window + * system has been initialized. The program should exit after calling this method. + */ +extern void displayMessage( _TCHAR* title, _TCHAR* message ); + +/* Load the specified shared library + */ +extern void * loadLibrary( _TCHAR * library ); + +/* Unload the shared library + */ +extern void unloadLibrary( void * handle ); + +/* Find the given symbol in the shared library + */ +extern void * findSymbol( void * handle, _TCHAR * symbol ); + +/* check the given path and attempt to make it absolute if it is relative */ +extern _TCHAR* checkPath( _TCHAR* path, _TCHAR* programDir, int reverseOrder ); + +extern _TCHAR * lastDirSeparator(_TCHAR* str); + +extern _TCHAR * firstDirSeparator(_TCHAR* str); +#endif diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c new file mode 100644 index 000000000..bc7a5cdc0 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Martin Oberhuber (Wind River) - [316975] memory leak on failure reading .ini file + *******************************************************************************/ + +#include "eclipseOS.h" +#include "eclipseConfig.h" + +#ifdef _WIN32 + +#include <stdio.h> +#include <sys/stat.h> + +#ifdef __MINGW32__ +#include <stdlib.h> +#endif + +#else /* Unix like platforms */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +#endif + +int readIniFile(_TCHAR* program, int *argc, _TCHAR ***argv) +{ + _TCHAR* config_file = NULL; + int result; + + if (program == NULL || argc == NULL || argv == NULL) return -1; + +#if defined(_WIN32) && defined(_WIN32_CONSOLE) + config_file = getIniFile(program, 1); +#else + config_file = getIniFile(program, 0); +#endif + + result = readConfigFile(config_file, argc, argv); + free(config_file); + return result; +} + +_TCHAR* getIniFile(_TCHAR* program, int consoleLauncher){ + _TCHAR* config_file = NULL; + + /* Get a copy with room for .ini at the end */ + config_file = malloc( (_tcslen(program) + 5) * sizeof(_TCHAR)); + _tcscpy(config_file, program); + +#ifdef _WIN32 + { + /* Search for the extension .exe and replace it with .ini */ + _TCHAR *extension = _tcsrchr(config_file, _T_ECLIPSE('.')); + if (extension == NULL) + { + /* does not end with an extension, just append .ini */ + extension = config_file + _tcslen(config_file); + } + _tcscpy(extension, _T_ECLIPSE(".ini")); + if(consoleLauncher){ + /* We are the console version, if the ini file does not exist, try + * removing the 'c' from the end of the program name */ + struct _stat stats; + if (_tstat( config_file, &stats ) != 0 && *(extension - 1) == _T('c')) { + _tcscpy(extension - 1, extension); + } + } + } +#else + /* Append the extension */ + strcat(config_file, ".ini"); +#endif + return config_file; +} + +int readConfigFile( _TCHAR * config_file, int *argc, _TCHAR ***argv ) +{ + _TCHAR * buffer; + _TCHAR * argument; + _TCHAR * arg; + FILE *file = NULL; + int maxArgs = 128; + int index; + size_t bufferSize = 1024; + size_t length; + + + /* Open the config file as a text file + * Note that carriage return-linefeed combination \r\n are automatically + * translated into single linefeeds on input in the t (translated) mode + * on windows, on other platforms we will strip the \r as whitespace. + */ + file = _tfopen(config_file, _T_ECLIPSE("rt")); + if (file == NULL) return -3; + + /* allocate buffers */ + buffer = (_TCHAR*)malloc(bufferSize * sizeof(_TCHAR)); + argument = (_TCHAR*)malloc(bufferSize * sizeof(_TCHAR)); + *argv = (_TCHAR **)malloc((1 + maxArgs) * sizeof(_TCHAR*)); + + index = 0; + + /* Parse every line */ + while (_fgetts(buffer, bufferSize, file) != NULL) + { + /* did we fill the buffer without reaching the end of a line? */ + while (buffer[bufferSize - 2] != _T_ECLIPSE('\n') && _tcslen(buffer) == (bufferSize - 1)) { + bufferSize += 1024; + buffer = (_TCHAR*)realloc(buffer, bufferSize * sizeof(_TCHAR)); + argument = (_TCHAR*)realloc(argument, bufferSize * sizeof(_TCHAR)); + buffer[bufferSize - 2] = 0; + + /* read the next chunk to overwrite the \0 left by the last read */ + if(_fgetts(buffer + bufferSize - 1025, 1025, file) == NULL) + break; + } + + /* Extract the string prior to the first newline character. + * We don't have to worry about \r\n combinations since the file + * is opened in translated mode. + */ + if (_stscanf(buffer, _T_ECLIPSE("%[^\n]"), argument) == 1) + { + /* watch for comments */ + if(argument[0] == _T_ECLIPSE('#')) + continue; + + arg = _tcsdup(argument); + length = _tcslen(arg); + + /* basic whitespace trimming */ + while (length > 0 && (arg[length - 1] == _T_ECLIPSE(' ') || + arg[length - 1] == _T_ECLIPSE('\t') || + arg[length - 1] == _T_ECLIPSE('\r'))) + { + arg[--length] = 0; + } + /* ignore empty lines */ + if (length == 0) { + free(arg); + continue; + } + + (*argv)[index] = arg; + index++; + + /* Grow the array of TCHAR*. Ensure one more entry is + * available for the final NULL entry + */ + if (index == maxArgs - 1) + { + maxArgs += 128; + *argv = (_TCHAR **)realloc(*argv, maxArgs * sizeof(_TCHAR*)); + } + } + } + (*argv)[index] = NULL; + *argc = index; + + fclose(file); + free(buffer); + free(argument); + return 0; +} + +void freeConfig(_TCHAR **argv) +{ + int index = 0; + if (argv == NULL) return; + while (argv[index] != NULL) + { + free(argv[index]); + index++; + } + free(argv); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.h b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.h new file mode 100644 index 000000000..cd8ef9c97 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef ECLIPSE_CONFIG_H +#define ECLIPSE_CONFIG_H + +/* Configuration file reading utilities */ + +/** + * Reads a configuration file for the corresponding + * program argument. + * e.g if the program argument contains "c:/folder/eclipse.exe" + * then the config file "c:/folder/eclipse.ini" will be parsed. + * On a Unix like platform, for a program argument "/usr/eclipse/eclipse" + * should correspond a configuration file "/usr/eclipse/eclipse.ini" + * + * This method will call readConfigFile to read the actual ini file + * + * This method will use getIniFile with a value for consoleLauncher that + * is determined at compile time. Clients who are not the actual + * win32 console executable should instead use getIniFile and readConfigFile. + * + * Returns 0 if success. + */ +extern int readIniFile(_TCHAR* program, int *argc, _TCHAR ***argv); + +/** + * Return the path to the launcher ini file for the corresponding program + * argument. On win32, an "eclipsec.exe' console launcher can use the "eclipse.ini" + * ini file. + * consoleLauncher : whether or not we are using the win32 "eclipsec" console launcher + * has no affect on other platforms + */ +extern _TCHAR* getIniFile(_TCHAR* program, int consoleLauncher); + +/** + * Reads the given configuration file + * The argument argv refers to a newly allocated array of strings. + * The first entry is the program name to mimic the expectations + * from a typical argv list. + * The last entry of that array is NULL. + * Each non NULL entry in that array must be freed by the caller + * as well as the array itself, using freeConfig(). + * The argument argc contains the number of string allocated. + * + * Returns 0 if success. + */ +extern int readConfigFile( _TCHAR * config_file, int *argc, _TCHAR ***argv ); +/** + * Free the memory allocated by readConfigFile(). + */ +extern void freeConfig(_TCHAR **args); + +#endif /* ECLIPSE_CONFIG_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.c b/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.c new file mode 100644 index 000000000..845c646c6 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.c @@ -0,0 +1,568 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseJNI.h" +#include "eclipseCommon.h" +#include "eclipseOS.h" +#include "eclipseShm.h" + +#include <stdlib.h> +#include <string.h> + + +static _TCHAR* failedToLoadLibrary = _T_ECLIPSE("Failed to load the JNI shared library \"%s\".\n"); +static _TCHAR* createVMSymbolNotFound = _T_ECLIPSE("The JVM shared library \"%s\"\ndoes not contain the JNI_CreateJavaVM symbol.\n"); +static _TCHAR* failedCreateVM = _T_ECLIPSE("Failed to create the Java Virtual Machine.\n"); +static _TCHAR* internalExpectedVMArgs = _T_ECLIPSE("Internal Error, the JVM argument list is empty.\n"); +static _TCHAR* mainClassNotFound = _T_ECLIPSE("Failed to find a Main Class in \"%s\".\n"); + +static JNINativeMethod natives[] = {{"_update_splash", "()V", (void *)&update_splash}, + {"_get_splash_handle", "()J", (void *)&get_splash_handle}, + {"_set_exit_data", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)&set_exit_data}, + {"_set_launcher_info", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)&set_launcher_info}, + {"_show_splash", "(Ljava/lang/String;)V", (void *)&show_splash}, + {"_takedown_splash", "()V", (void *)&takedown_splash}}; + +/* local methods */ +static jstring newJavaString(JNIEnv *env, _TCHAR * str); +static void registerNatives(JNIEnv *env); +static int shouldShutdown(JNIEnv *env); +static void JNI_ReleaseStringChars(JNIEnv *env, jstring s, const _TCHAR* data); +static const _TCHAR* JNI_GetStringChars(JNIEnv *env, jstring str); +static char * getMainClass(JNIEnv *env, _TCHAR * jarFile); +static void setLibraryLocation(JNIEnv *env, jobject obj); + +static JavaVM * jvm = 0; +static JNIEnv *env = 0; + +/* cache String class and methods to avoid looking them up all the time */ +static jclass string_class = NULL; +#if !defined(UNICODE) && !defined(MACOSX) +static jmethodID string_getBytesMethod = NULL; +static jmethodID string_ctor = NULL; +#endif + +/* JNI Callback methods */ +JNIEXPORT void JNICALL set_exit_data(JNIEnv * env, jobject obj, jstring id, jstring s){ + const _TCHAR* data = NULL; + const _TCHAR* sharedId = NULL; + size_t length; + + if(s != NULL) { + length = (*env)->GetStringLength(env, s); + if(!(*env)->ExceptionOccurred(env)) { + data = JNI_GetStringChars(env, s); + if (data != NULL) { + if(id != NULL) { + sharedId = JNI_GetStringChars(env, id); + if(sharedId != NULL) { + setSharedData(sharedId, data); + JNI_ReleaseStringChars(env, id, sharedId); + } + } else { + exitData = malloc((length + 1) * sizeof(_TCHAR*)); + _tcsncpy( exitData, data, length); + exitData[length] = _T_ECLIPSE('\0'); + } + JNI_ReleaseStringChars(env, s, data); + } + } + if(data == NULL && sharedId == NULL) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } +} + +JNIEXPORT void JNICALL set_launcher_info(JNIEnv * env, jobject obj, jstring launcher, jstring name){ + const _TCHAR* launcherPath = NULL; + const _TCHAR* launcherName = NULL; + + if (launcher != NULL) { + launcherPath = JNI_GetStringChars(env, launcher); + if (launcherPath != NULL) { + setProgramPath(_tcsdup(launcherPath)); + JNI_ReleaseStringChars(env, launcher, launcherPath); + } + } + + if (name != NULL) { + launcherName = JNI_GetStringChars(env, name); + if (launcherName != NULL) { + setOfficialName(_tcsdup(launcherName)); + JNI_ReleaseStringChars(env, name, launcherName); + } + } +} + + +JNIEXPORT void JNICALL update_splash(JNIEnv * env, jobject obj){ + dispatchMessages(); +} + +JNIEXPORT jlong JNICALL get_splash_handle(JNIEnv * env, jobject obj){ + return getSplashHandle(); +} + +JNIEXPORT void JNICALL show_splash(JNIEnv * env, jobject obj, jstring s){ + const _TCHAR* data = NULL; + + setLibraryLocation(env, obj); + + if(s != NULL) { + data = JNI_GetStringChars(env, s); + if(data != NULL) { + showSplash(data); + JNI_ReleaseStringChars(env, s, data); + } else { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } +} + +JNIEXPORT void JNICALL takedown_splash(JNIEnv * env, jobject obj){ + takeDownSplash(); +} + +/* + * On AIX we need the location of the eclipse shared library so that we + * can find the libeclipse-motif.so library. Reach into the JNIBridge + * object to get the "library" field. + */ +static void setLibraryLocation(JNIEnv * env, jobject obj) { + jclass bridge = (*env)->FindClass(env, "org/eclipse/equinox/launcher/JNIBridge"); + if (bridge != NULL) { + jfieldID libraryField = (*env)->GetFieldID(env, bridge, "library", "Ljava/lang/String;"); + if (libraryField != NULL) { + jstring stringObject = (jstring) (*env)->GetObjectField(env, obj, libraryField); + if (stringObject != NULL) { + const _TCHAR * str = JNI_GetStringChars(env, stringObject); + eclipseLibrary = _tcsdup(str); + JNI_ReleaseStringChars(env, stringObject, str); + } + } + } + if( (*env)->ExceptionOccurred(env) != 0 ){ + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } +} + +static void registerNatives(JNIEnv *env) { + jclass bridge = (*env)->FindClass(env, "org/eclipse/equinox/launcher/JNIBridge"); + if(bridge != NULL) { + int numNatives = sizeof(natives) / sizeof(natives[0]); + (*env)->RegisterNatives(env, bridge, natives, numNatives); + } + if( (*env)->ExceptionOccurred(env) != 0 ){ + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } +} + + +/* Get a _TCHAR* from a jstring, string should be released later with JNI_ReleaseStringChars */ +static const _TCHAR * JNI_GetStringChars(JNIEnv *env, jstring str) { + const _TCHAR * result = NULL; +#ifdef UNICODE + /* GetStringChars is not null terminated, make a copy */ + const _TCHAR * stringChars = (*env)->GetStringChars(env, str, 0); + int length = (*env)->GetStringLength(env, str); + _TCHAR * copy = malloc( (length + 1) * sizeof(_TCHAR)); + _tcsncpy(copy, stringChars, length); + copy[length] = _T_ECLIPSE('\0'); + (*env)->ReleaseStringChars(env, str, stringChars); + result = copy; +#elif MACOSX + /* Use UTF on the Mac */ + result = (*env)->GetStringUTFChars(env, str, 0); +#else + /* Other platforms, use java's default encoding */ + _TCHAR* buffer = NULL; + if (string_class == NULL) + string_class = (*env)->FindClass(env, "java/lang/String"); + if (string_class != NULL) { + if (string_getBytesMethod == NULL) + string_getBytesMethod = (*env)->GetMethodID(env, string_class, "getBytes", "()[B"); + if (string_getBytesMethod != NULL) { + jbyteArray bytes = (*env)->CallObjectMethod(env, str, string_getBytesMethod); + if (!(*env)->ExceptionOccurred(env)) { + jsize length = (*env)->GetArrayLength(env, bytes); + buffer = malloc( (length + 1) * sizeof(_TCHAR*)); + (*env)->GetByteArrayRegion(env, bytes, 0, length, (jbyte*)buffer); + buffer[length] = 0; + } + (*env)->DeleteLocalRef(env, bytes); + } + } + if(buffer == NULL) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + result = buffer; +#endif + return result; +} + +/* Release the string that was obtained using JNI_GetStringChars */ +static void JNI_ReleaseStringChars(JNIEnv *env, jstring s, const _TCHAR* data) { +#ifdef UNICODE + free((_TCHAR*)data); +#elif MACOSX + (*env)->ReleaseStringUTFChars(env, s, data); +#else + free((_TCHAR*)data); +#endif +} + +static jstring newJavaString(JNIEnv *env, _TCHAR * str) +{ + jstring newString = NULL; +#ifdef UNICODE + size_t length = _tcslen(str); + newString = (*env)->NewString(env, str, length); +#elif MACOSX + newString = (*env)->NewStringUTF(env, str); +#else + size_t length = _tcslen(str); + jbyteArray bytes = (*env)->NewByteArray(env, length); + if(bytes != NULL) { + (*env)->SetByteArrayRegion(env, bytes, 0, length, (jbyte *)str); + if (!(*env)->ExceptionOccurred(env)) { + if (string_class == NULL) + string_class = (*env)->FindClass(env, "java/lang/String"); + if(string_class != NULL) { + if (string_ctor == NULL) + string_ctor = (*env)->GetMethodID(env, string_class, "<init>", "([B)V"); + if(string_ctor != NULL) { + newString = (*env)->NewObject(env, string_class, string_ctor, bytes); + } + } + } + (*env)->DeleteLocalRef(env, bytes); + } +#endif + if(newString == NULL) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + return newString; +} + +static jobjectArray createRunArgs( JNIEnv *env, _TCHAR * args[] ) { + int index = 0, length = -1; + jobjectArray stringArray = NULL; + jstring string; + + /*count the number of elements first*/ + while(args[++length] != NULL); + + if (string_class == NULL) + string_class = (*env)->FindClass(env, "java/lang/String"); + if(string_class != NULL) { + stringArray = (*env)->NewObjectArray(env, length, string_class, 0); + if(stringArray != NULL) { + for( index = 0; index < length; index++) { + string = newJavaString(env, args[index]); + if(string != NULL) { + (*env)->SetObjectArrayElement(env, stringArray, index, string); + (*env)->DeleteLocalRef(env, string); + } else { + (*env)->DeleteLocalRef(env, stringArray); + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + return NULL; + } + } + } + } + if(stringArray == NULL) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + return stringArray; +} + +JavaResults * startJavaJNI( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ) +{ + int i; + int numVMArgs = -1; + void * jniLibrary; + JNI_createJavaVM createJavaVM; + JavaVMInitArgs init_args; + JavaVMOption * options; + char * mainClassName = NULL; + JavaResults * results = NULL; + + /* JNI reflection */ + jclass mainClass = NULL; /* The Main class to load */ + jmethodID mainConstructor = NULL; /* Main's default constructor Main() */ + jobject mainObject = NULL; /* An instantiation of the main class */ + jmethodID runMethod = NULL; /* Main.run(String[]) */ + jobjectArray methodArgs = NULL; /* Arguments to pass to run */ + + results = malloc(sizeof(JavaResults)); + memset(results, 0, sizeof(JavaResults)); + + jniLibrary = loadLibrary(libPath); + if(jniLibrary == NULL) { + results->launchResult = -1; + results->errorMessage = malloc((_tcslen(failedToLoadLibrary) + _tcslen(libPath) + 1) * sizeof(_TCHAR)); + _stprintf(results->errorMessage, failedToLoadLibrary, libPath); + return results; /*error*/ + } + + createJavaVM = (JNI_createJavaVM)findSymbol(jniLibrary, _T_ECLIPSE("JNI_CreateJavaVM")); + if(createJavaVM == NULL) { + results->launchResult = -2; + results->errorMessage = malloc((_tcslen(createVMSymbolNotFound) + _tcslen(libPath) + 1) * sizeof(_TCHAR)); + _stprintf(results->errorMessage, createVMSymbolNotFound, libPath); + return results; /*error*/ + } + + /* count the vm args */ + while(vmArgs[++numVMArgs] != NULL) {} + + if(numVMArgs <= 0) { + /*error, we expect at least the required vm arg */ + results->launchResult = -3; + results->errorMessage = _tcsdup(internalExpectedVMArgs); + return results; + } + + options = malloc(numVMArgs * sizeof(JavaVMOption)); + for(i = 0; i < numVMArgs; i++){ + options[i].optionString = toNarrow(vmArgs[i]); + options[i].extraInfo = 0; + } + +#ifdef MACOSX + init_args.version = JNI_VERSION_1_4; +#else + init_args.version = JNI_VERSION_1_2; +#endif + init_args.options = options; + init_args.nOptions = numVMArgs; + init_args.ignoreUnrecognized = JNI_TRUE; + + if( createJavaVM(&jvm, &env, &init_args) == 0 ) { + registerNatives(env); + + mainClassName = getMainClass(env, jarFile); + if (mainClassName != NULL) { + mainClass = (*env)->FindClass(env, mainClassName); + free(mainClassName); + } + + if (mainClass == NULL) { + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + mainClass = (*env)->FindClass(env, "org/eclipse/equinox/launcher/Main"); + } + + if(mainClass != NULL) { + results->launchResult = -6; /* this will be reset to 0 below on success */ + mainConstructor = (*env)->GetMethodID(env, mainClass, "<init>", "()V"); + if(mainConstructor != NULL) { + mainObject = (*env)->NewObject(env, mainClass, mainConstructor); + if(mainObject != NULL) { + runMethod = (*env)->GetMethodID(env, mainClass, "run", "([Ljava/lang/String;)I"); + if(runMethod != NULL) { + methodArgs = createRunArgs(env, progArgs); + if(methodArgs != NULL) { + results->launchResult = 0; + results->runResult = (*env)->CallIntMethod(env, mainObject, runMethod, methodArgs); + (*env)->DeleteLocalRef(env, methodArgs); + } + } + (*env)->DeleteLocalRef(env, mainObject); + } + } + } else { + results->launchResult = -5; + results->errorMessage = malloc((_tcslen(mainClassNotFound) + _tcslen(jarFile) + 1) * sizeof(_TCHAR)); + _stprintf(results->errorMessage, mainClassNotFound, jarFile); + } + if((*env)->ExceptionOccurred(env)){ + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + + } else { + results->launchResult = -4; + results->errorMessage = _tcsdup(failedCreateVM); + } + + /* toNarrow allocated new strings, free them */ + for(i = 0; i < numVMArgs; i++){ + free( options[i].optionString ); + } + free(options); + return results; +} + +static char * getMainClass(JNIEnv *env, _TCHAR * jarFile) { + jclass jarFileClass = NULL, manifestClass = NULL, attributesClass = NULL; + jmethodID jarFileConstructor = NULL, getManifestMethod = NULL, getMainAttributesMethod = NULL, closeJarMethod = NULL, getValueMethod = NULL; + jobject jarFileObject, manifest, attributes; + jstring mainClassString = NULL; + jstring jarFileString, headerString; + const _TCHAR *mainClass; + + /* get the classes we need */ + jarFileClass = (*env)->FindClass(env, "java/util/jar/JarFile"); + if (jarFileClass != NULL) { + manifestClass = (*env)->FindClass(env, "java/util/jar/Manifest"); + if (manifestClass != NULL) { + attributesClass = (*env)->FindClass(env, "java/util/jar/Attributes"); + } + } + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + if (attributesClass == NULL) + return NULL; + + /* find the methods */ + jarFileConstructor = (*env)->GetMethodID(env, jarFileClass, "<init>", "(Ljava/lang/String;Z)V"); + if(jarFileConstructor != NULL) { + getManifestMethod = (*env)->GetMethodID(env, jarFileClass, "getManifest", "()Ljava/util/jar/Manifest;"); + if(getManifestMethod != NULL) { + closeJarMethod = (*env)->GetMethodID(env, jarFileClass, "close", "()V"); + if (closeJarMethod != NULL) { + getMainAttributesMethod = (*env)->GetMethodID(env, manifestClass, "getMainAttributes", "()Ljava/util/jar/Attributes;"); + if (getMainAttributesMethod != NULL) { + getValueMethod = (*env)->GetMethodID(env, attributesClass, "getValue", "(Ljava/lang/String;)Ljava/lang/String;"); + } + } + } + } + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + if (getValueMethod == NULL) + return NULL; + + /* jarFileString = new String(jarFile); */ + jarFileString = newJavaString(env, jarFile); + /* headerString = new String("Main-Class"); */ + headerString = newJavaString(env, _T_ECLIPSE("Main-Class")); + if (jarFileString != NULL && headerString != NULL) { + /* jarfileObject = new JarFile(jarFileString, false); */ + jarFileObject = (*env)->NewObject(env, jarFileClass, jarFileConstructor, jarFileString, JNI_FALSE); + if (jarFileObject != NULL) { + /* manifest = jarFileObject.getManifest(); */ + manifest = (*env)->CallObjectMethod(env, jarFileObject, getManifestMethod); + if (manifest != NULL) { + /*jarFileObject.close() */ + (*env)->CallVoidMethod(env, jarFileObject, closeJarMethod); + if (!(*env)->ExceptionOccurred(env)) { + /* attributes = manifest.getMainAttributes(); */ + attributes = (*env)->CallObjectMethod(env, manifest, getMainAttributesMethod); + if (attributes != NULL) { + /* mainClassString = attributes.getValue(headerString); */ + mainClassString = (*env)->CallObjectMethod(env, attributes, getValueMethod, headerString); + } + } + } + (*env)->DeleteLocalRef(env, jarFileObject); + } + } + + if (jarFileString != NULL) + (*env)->DeleteLocalRef(env, jarFileString); + if (headerString != NULL) + (*env)->DeleteLocalRef(env, headerString); + + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + + if (mainClassString == NULL) + return NULL; + + mainClass = JNI_GetStringChars(env, mainClassString); + if(mainClass != NULL) { + int i = -1; + char *result = toNarrow(mainClass); + JNI_ReleaseStringChars(env, mainClassString, mainClass); + + /* replace all the '.' with '/' */ + while(result[++i] != '\0') { + if(result[i] == '.') + result[i] = '/'; + } + return result; + } + return NULL; +} + +void cleanupVM(int exitCode) { + JNIEnv * localEnv = env; + if (jvm == 0) + return; + + if (secondThread) + (*jvm)->AttachCurrentThread(jvm, (void**)&localEnv, NULL); + else + localEnv = env; + if (localEnv == 0) + return; + + /* we call System.exit() unless osgi.noShutdown is set */ + if (shouldShutdown(env)) { + jclass systemClass = NULL; + jmethodID exitMethod = NULL; + systemClass = (*env)->FindClass(env, "java/lang/System"); + if (systemClass != NULL) { + exitMethod = (*env)->GetStaticMethodID(env, systemClass, "exit", "(I)V"); + if (exitMethod != NULL) { + (*env)->CallStaticVoidMethod(env, systemClass, exitMethod, exitCode); + } + } + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } + (*jvm)->DestroyJavaVM(jvm); +} + +static int shouldShutdown(JNIEnv * env) { + jclass booleanClass = NULL; + jmethodID method = NULL; + jstring arg = NULL; + jboolean result = 0; + + booleanClass = (*env)->FindClass(env, "java/lang/Boolean"); + if (booleanClass != NULL) { + method = (*env)->GetStaticMethodID(env, booleanClass, "getBoolean", "(Ljava/lang/String;)Z"); + if (method != NULL) { + arg = newJavaString(env, _T_ECLIPSE("osgi.noShutdown")); + result = (*env)->CallStaticBooleanMethod(env, booleanClass, method, arg); + (*env)->DeleteLocalRef(env, arg); + } + } + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + return (result == 0); +} + + diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.h b/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.h new file mode 100644 index 000000000..3ef4b89dc --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseJNI.h @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +#ifndef ECLIPSE_JNI_H +#define ECLIPSE_JNI_H + +#include "eclipseUnicode.h" +#include <jni.h> + +typedef struct { + int launchResult; + int runResult; + _TCHAR * errorMessage; +} JavaResults; + +typedef jint (JNICALL *JNI_createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args); + +/* JNI Callback methods */ +/* Use name mangling since we may be linking these from java with System.LoadLibrary */ +#define set_exit_data Java_org_eclipse_equinox_launcher_JNIBridge__1set_1exit_1data +#define set_launcher_info Java_org_eclipse_equinox_launcher_JNIBridge__1set_1launcher_1info +#define update_splash Java_org_eclipse_equinox_launcher_JNIBridge__1update_1splash +#define show_splash Java_org_eclipse_equinox_launcher_JNIBridge__1show_1splash +#define get_splash_handle Java_org_eclipse_equinox_launcher_JNIBridge__1get_1splash_1handle +#define takedown_splash Java_org_eclipse_equinox_launcher_JNIBridge__1takedown_1splash + +#ifdef __cplusplus +extern "C" { +#endif +/* + * org_eclipse_equinox_launcher_JNIBridge#_set_exit_data + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL set_exit_data(JNIEnv *, jobject, jstring, jstring); + +/* + * org_eclipse_equinox_launcher_JNIBridge#_set_launcher_info + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL set_launcher_info(JNIEnv *, jobject, jstring, jstring); + +/* + * org_eclipse_equinox_launcher_JNIBridge#_update_splash + * Signature: ()V + */ +JNIEXPORT void JNICALL update_splash(JNIEnv *, jobject); + +/* + * org_eclipse_equinox_launcher_JNIBridge#_get_splash_handle + * Signature: ()J + */ +JNIEXPORT jlong JNICALL get_splash_handle(JNIEnv *, jobject); + +/* + * org_eclipse_equinox_launcher_JNIBridge#_show_splash + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL show_splash(JNIEnv *, jobject, jstring); + +/* + * org_eclipse_equinox_launcher_JNIBridge#_takedown_splash + * Signature: ()V + */ +JNIEXPORT void JNICALL takedown_splash(JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif + +/* Start the Java VM and Wait For It to Terminate + * + * This method is responsible for starting the Java VM and for + * detecting its termination. The resulting JVM exit code should + * be returned to the main launcher, which will display a message if + * the termination was not normal. + */ +extern JavaResults* startJavaJNI( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ); + +extern void cleanupVM( int ); +#endif diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseMain.c b/features/org.eclipse.equinox.executable.feature/library/eclipseMain.c new file mode 100644 index 000000000..c45f3656f --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseMain.c @@ -0,0 +1,468 @@ +/******************************************************************************* + * Copyright (c) 2006, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseUnicode.h" +#include "eclipseCommon.h" +#include "eclipseConfig.h" + +#ifdef _WIN32 +#include <direct.h> +#else +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <locale.h> +#include <sys/stat.h> + +static _TCHAR* libraryMsg = +_T_ECLIPSE("The %s executable launcher was unable to locate its \n\ +companion shared library."); + +static _TCHAR* entryMsg = +_T_ECLIPSE("There was a problem loading the shared library and \n\ +finding the entry point."); + +#define NAME _T_ECLIPSE("-name") +#define VMARGS _T_ECLIPSE("-vmargs") /* special option processing required */ +/* New arguments have the form --launcher.<arg> to avoid collisions */ +#define LIBRARY _T_ECLIPSE("--launcher.library") +#define SUPRESSERRORS _T_ECLIPSE("--launcher.suppressErrors") +#define INI _T_ECLIPSE("--launcher.ini") + +/* this typedef must match the run method in eclipse.c */ +typedef int (*RunMethod)(int argc, _TCHAR* argv[], _TCHAR* vmArgs[]); +typedef void (*SetInitialArgs)(int argc, _TCHAR*argv[], _TCHAR* library); + +static _TCHAR* name = NULL; /* program name */ +static _TCHAR** userVMarg = NULL; /* user specific args for the Java VM */ +static _TCHAR* programDir = NULL; /* directory where program resides */ +static _TCHAR* officialName = NULL; +static int suppressErrors = 0; /* supress error dialogs */ + +static int createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv); +static void parseArgs( int* argc, _TCHAR* argv[] ); +static _TCHAR* getDefaultOfficialName(_TCHAR* program); +static _TCHAR* findProgram(_TCHAR* argv[]); +static _TCHAR* findLibrary(_TCHAR* library, _TCHAR* program); +static _TCHAR* checkForIni(int argc, _TCHAR* argv[]); +static _TCHAR* getDirFromProgram(_TCHAR* program); + +static int initialArgc; +static _TCHAR** initialArgv; + +_TCHAR* eclipseLibrary = NULL; /* path to the eclipse shared library */ + +#ifdef UNICODE +extern int main(int, char**); +int mainW(int, wchar_t**); +int wmain( int argc, wchar_t** argv ) { + return mainW(argc, argv); +} + +int main(int argc, char* argv[]) { + /* + * Run the UNICODE version, convert the arguments from MBCS to UNICODE + */ + int i, result; + wchar_t **newArgv = malloc((argc + 1) * sizeof(wchar_t *)); + for (i=0; i<argc; i++) { + char *oldArg = argv[i]; + int numChars = MultiByteToWideChar(CP_ACP, 0, oldArg, -1, NULL, 0); + wchar_t *newArg = malloc((numChars + 1) * sizeof(wchar_t)); + newArg[numChars] = 0; + MultiByteToWideChar(CP_ACP, 0, oldArg, -1, newArg, numChars); + newArgv[i] = newArg; + } + newArgv[i] = NULL; + result = mainW(argc, newArgv); + for (i=0; i<argc; i++) { + free(newArgv[i]); + } + free(newArgv); + return result; +} + +#define main mainW +#endif /* UNICODE */ + +int main( int argc, _TCHAR* argv[] ) +{ + _TCHAR* errorMsg; + _TCHAR* program; + _TCHAR* iniFile; + _TCHAR* ch; + _TCHAR** configArgv = NULL; + int configArgc = 0; + int exitCode = 0; + int ret = 0; + void * handle = 0; + RunMethod runMethod; + SetInitialArgs setArgs; + + setlocale(LC_ALL, ""); + + initialArgc = argc; + initialArgv = malloc((argc + 1) * sizeof(_TCHAR*)); + memcpy(initialArgv, argv, (argc + 1) * sizeof(_TCHAR*)); + + /* + * Strip off any extroneous <CR> from the last argument. If a shell script + * on Linux is created in DOS format (lines end with <CR><LF>), the C-shell + * does not strip off the <CR> and hence the argument is bogus and may + * not be recognized by the launcher or eclipse itself. + */ + ch = _tcschr( argv[ argc - 1 ], _T_ECLIPSE('\r') ); + if (ch != NULL) + { + *ch = _T_ECLIPSE('\0'); + } + + /* Determine the full pathname of this program. */ + program = findProgram(argv); + + /* Parse configuration file arguments */ + iniFile = checkForIni(argc, argv); + if (iniFile != NULL) + ret = readConfigFile(iniFile, &configArgc, &configArgv); + else + ret = readIniFile(program, &configArgc, &configArgv); + if (ret == 0) + { + parseArgs (&configArgc, configArgv); + } + + /* Parse command line arguments */ + /* Overrides configuration file arguments */ + parseArgs( &argc, argv ); + + /* Special case - user arguments specified in the config file + * are appended to the user arguments passed from the command line. + */ + if (configArgc > 0) + { + createUserArgs(configArgc, configArgv, &argc, &argv); + } + + /* Initialize official program name */ + officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName(program); + + /* Find the directory where the Eclipse program is installed. */ + programDir = getDirFromProgram(program); + + /* Find the eclipse library */ + eclipseLibrary = findLibrary(eclipseLibrary, program); + + if(eclipseLibrary != NULL) + handle = loadLibrary(eclipseLibrary); + if(handle == NULL) { + errorMsg = malloc( (_tcslen(libraryMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) ); + _stprintf( errorMsg, libraryMsg, officialName ); + if (!suppressErrors) + displayMessage( officialName, errorMsg ); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, errorMsg); + free( errorMsg ); + exit( 1 ); + } + + setArgs = (SetInitialArgs)findSymbol(handle, SET_INITIAL_ARGS); + if(setArgs != NULL) + setArgs(initialArgc, initialArgv, eclipseLibrary); + else { + if(!suppressErrors) + displayMessage(officialName, entryMsg); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, entryMsg); + exit(1); + } + + runMethod = (RunMethod)findSymbol(handle, RUN_METHOD); + if(runMethod != NULL) + exitCode = runMethod(argc, argv, userVMarg); + else { + if(!suppressErrors) + displayMessage(officialName, entryMsg); + else + _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, entryMsg); + exit(1); + } + unloadLibrary(handle); + + free( eclipseLibrary ); + free( programDir ); + free( program ); + free( officialName ); + + return exitCode; +} + +_TCHAR* getProgramPath() { + return NULL; +} + +static _TCHAR* findProgram(_TCHAR* argv[]) { + _TCHAR * program; +#ifdef _WIN32 + /* windows, make sure we are looking for the .exe */ + _TCHAR * ch; + int length = _tcslen(argv[0]); + ch = malloc( (length + 5) * sizeof(_TCHAR)); + _tcscpy(ch, argv[0]); + + if (length <= 4 || _tcsicmp( &ch[ length - 4 ], _T_ECLIPSE(".exe") ) != 0) + _tcscat(ch, _T_ECLIPSE(".exe")); + + program = findCommand(ch); + if (ch != program) + free(ch); +#else + program = findCommand( argv[0] ); +#endif + if (program == NULL) + { +#ifdef _WIN32 + program = malloc( MAX_PATH_LENGTH + 1 ); + GetModuleFileName( NULL, program, MAX_PATH_LENGTH ); + argv[0] = program; +#else + program = malloc( (strlen( argv[0] ) + 1) * sizeof(_TCHAR) ); + strcpy( program, argv[0] ); +#endif + } else if (_tcscmp(argv[0], program) != 0) { + argv[0] = program; + } + return program; +} + +/* + * Parse arguments of the command. + */ +static void parseArgs( int* pArgc, _TCHAR* argv[] ) +{ + int index; + + /* Ensure the list of user argument is NULL terminated. */ + argv[ *pArgc ] = NULL; + + /* For each user defined argument */ + for (index = 0; index < *pArgc; index++){ + if(_tcsicmp(argv[index], VMARGS) == 0) { + userVMarg = &argv[ index+1 ]; + argv[ index ] = NULL; + *pArgc = index; + } else if(_tcsicmp(argv[index], NAME) == 0) { + name = argv[++index]; + } else if(_tcsicmp(argv[index], LIBRARY) == 0) { + eclipseLibrary = argv[++index]; + } else if(_tcsicmp(argv[index], SUPRESSERRORS) == 0) { + suppressErrors = 1; + } + } +} + +/* We need to look for --launcher.ini before parsing the other args */ +static _TCHAR* checkForIni(int argc, _TCHAR* argv[]) +{ + int index; + for(index = 0; index < (argc - 1); index++) { + if(_tcsicmp(argv[index], INI) == 0) { + return argv[++index]; + } + } + return NULL; +} + +/* + * Create a new array containing user arguments from the config file first and + * from the command line second. + * Allocate an array large enough to host all the strings passed in from + * the argument configArgv and argv. That array is passed back to the + * argv argument. That array must be freed with the regular free(). + * Note that both arg lists are expected to contain the argument 0 from the C + * main method. That argument contains the path/executable name. It is + * only copied once in the resulting list. + * + * Returns 0 if success. + */ +static int createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv) +{ + _TCHAR** newArray = (_TCHAR **)malloc((configArgc + *argc + 1) * sizeof(_TCHAR *)); + + newArray[0] = (*argv)[0]; /* use the original argv[0] */ + memcpy(newArray + 1, configArgv, configArgc * sizeof(_TCHAR *)); + + /* Skip the argument zero (program path and name) */ + memcpy(newArray + 1 + configArgc, *argv + 1, (*argc - 1) * sizeof(_TCHAR *)); + + /* Null terminate the new list of arguments and return it. */ + *argv = newArray; + *argc += configArgc; + (*argv)[*argc] = NULL; + + return 0; +} + +/* Determine the Program Directory + * + * This function takes the directory where program executable resides and + * determines the installation directory. + */ +_TCHAR* getDirFromProgram(_TCHAR* program) +{ + _TCHAR* ch; + + if(programDir != NULL) + return programDir; + + programDir = malloc( (_tcslen( program ) + 1) * sizeof(_TCHAR) ); + _tcscpy( programDir, program ); + ch = lastDirSeparator( programDir ); + if (ch != NULL) + { + *(ch+1) = _T_ECLIPSE('\0'); + return programDir; + } + + /* Can't figure out from the program, lets use the cwd */ + free(programDir); + programDir = malloc( MAX_PATH_LENGTH * sizeof (_TCHAR)); + _tgetcwd( programDir, MAX_PATH_LENGTH ); + return programDir; +} + +_TCHAR* getProgramDir() +{ + return programDir; +} + +_TCHAR* getOfficialName() { + return officialName; +} + +/* + * Determine the default official application name + * + * This function provides the default application name that appears in a variety of + * places such as: title of message dialog, title of splash screen window + * that shows up in Windows task bar. + * It is computed from the name of the launcher executable and + * by capitalizing the first letter. e.g. "c:/ide/eclipse.exe" provides + * a default name of "Eclipse". + */ +static _TCHAR* getDefaultOfficialName(_TCHAR* program) +{ + _TCHAR *ch = NULL; + + /* Skip the directory part */ + ch = lastDirSeparator( program ); + if (ch == NULL) ch = program; + else ch++; + + ch = _tcsdup( ch ); +#ifdef _WIN32 + { + /* Search for the extension .exe and cut it */ + _TCHAR *extension = _tcsrchr(ch, _T_ECLIPSE('.')); + if (extension != NULL) + { + *extension = _T_ECLIPSE('\0'); + } + } +#endif + /* Upper case the first character */ +#ifndef LINUX + { + *ch = _totupper(*ch); + } +#else + { + if (*ch >= 'a' && *ch <= 'z') + { + *ch -= 32; + } + } +#endif + return ch; +} + +static _TCHAR* findLibrary(_TCHAR* library, _TCHAR* program) +{ + _TCHAR* c; + _TCHAR* path; + _TCHAR* fragment; + _TCHAR* result; + _TCHAR* dot = _T_ECLIPSE("."); + size_t progLength, pathLength; + size_t fragmentLength; + struct _stat stats; + + if (library != NULL) { + path = checkPath(library, programDir, 1); + if (_tstat(path, &stats) == 0 && (stats.st_mode & S_IFDIR) != 0) + { + /* directory, find the highest version eclipse_* library */ + result = findFile(path, _T_ECLIPSE("eclipse")); + } else { + /* file, return it */ + result = _tcsdup(path); + } + + if (path != library) + free(path); + return result; + } + + /* build the equinox.launcher fragment name */ + fragmentLength = _tcslen(DEFAULT_EQUINOX_STARTUP) + 1 + _tcslen(wsArg) + 1 + _tcslen(osArg) + 1 + _tcslen(osArchArg) + 1; + fragment = malloc(fragmentLength * sizeof(_TCHAR)); + _tcscpy(fragment, DEFAULT_EQUINOX_STARTUP); + _tcscat(fragment, dot); + _tcscat(fragment, wsArg); + _tcscat(fragment, dot); + _tcscat(fragment, osArg); + //!(fragmentOS.equals(Constants.OS_MACOSX) && !Constants.ARCH_X86_64.equals(fragmentArch)) +#if !(defined(MACOSX) && !defined(__x86_64__)) + /* The Mac fragment covers both archs and does not have that last segment */ + _tcscat(fragment, dot); + _tcscat(fragment, osArchArg); +#endif + progLength = pathLength = _tcslen(programDir); +#ifdef MACOSX + pathLength += 9; +#endif + path = malloc( (pathLength + 1 + 7 + 1) * sizeof(_TCHAR)); + _tcscpy(path, programDir); + if (!IS_DIR_SEPARATOR(path[progLength - 1])) { + path[progLength] = dirSeparator; + path[progLength + 1] = 0; + } +#ifdef MACOSX + _tcscat(path, _T_ECLIPSE("../../../")); +#endif + _tcscat(path, _T_ECLIPSE("plugins")); + + c = findFile(path, fragment); + free(fragment); + if (c == NULL) + return c; + fragment = c; + + result = findFile(fragment, _T_ECLIPSE("eclipse")); + + free(fragment); + free(path); + + return result; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.c b/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.c new file mode 100644 index 000000000..a599589d5 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.c @@ -0,0 +1,300 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* Eclipse Mozilla Utility Methods */ + +#ifdef MOZILLA_FIX + +#include "eclipseMozilla.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <sys/stat.h> + +static char* prefixes[] = { + "xulrunner-1", + "mozilla-seamonkey-1", + "seamonkey-1", + "mozilla-1", + "mozilla-firefox-2", + "firefox-2", + "mozilla-firefox-3", + "firefox-3", + NULL +}; +static const int XULRUNNER_INDEX = 0; + +/* Filter function used by fixEnvForMozilla() for finding directories + * with a desired prefix. + */ +int filter(const struct dirent *dir) +{ +#if defined(__amd64__) || defined(__x86_64__) || defined(__powerpc64__) + char* root = "/usr/lib64/"; +#else + char* root = "/usr/lib/"; +#endif + +#if defined (SOLARIS) + /* + * The solaris compiler does not do static linking, so just check + * for a common lib to ensure that the install seems valid. + */ + char* testlib = "/libxpcom.so"; +#else + /* Ensure that the install is dynamically-linked and is built with GTK2 */ + char* testlib = "/components/libwidget_gtk2.so"; +#endif + + struct stat buf; + int index = 0; + char* dirname = (char *)dir->d_name; + + char* prefix = prefixes [index]; + while (prefix != NULL) + { + int prefixLength = strlen(prefix); + if (strncmp(dirname, prefix, prefixLength) == 0) + { + /* If a xulrunner install is found then success is immediate since + * xulrunner always provides an embeddable GRE. + */ + if (index == XULRUNNER_INDEX) return 1; /* include in scandir result */ + + int dirLength = strlen(dirname); + char* testpath = malloc (strlen(root) + dirLength + strlen(testlib) + 1); + strcpy(testpath, root); + strcat(testpath, dirname); + strcat(testpath, testlib); + int success = stat(testpath, &buf) == 0; + free(testpath); + if (success) + { + return 1; /* include in scandir result */ + } + } + prefix = prefixes [++index]; + } + return 0; /* exclude from scandir result */ +} + +#if defined (SOLARIS) +/* + * A replacement for + * scandir(const char *dir, struct dirent ***namelist, filter, alphasort); + * because scandir & alphasort don't exist on Solaris 9. + * Return the dirent->d_name that was sorted the highest according to strcoll, + * or NULL on error or if no entries matched the filter. + * The caller is responsible for freeing the returned string + */ +char * scan(const char * path) { + DIR *dir = NULL; + struct dirent * entry = NULL; + char * candidate = NULL; + + if ((dir = opendir(path)) == NULL) { + return NULL; + } + + while ((entry = readdir(dir)) != NULL) { + if (filter(entry)) { + if (candidate == NULL) { + candidate = strdup(entry->d_name); + } else if (strcoll(candidate, entry->d_name) < 0) { + free(candidate); + candidate = strdup(entry->d_name); + } + } + } + closedir(dir); + + return candidate; +} +#endif + +/* Set the environmnent required by the SWT Browser widget to bind to Mozilla. + * The SWT Browser widget relies on Mozilla on Linux. The LD_LIBRARY_PATH + * and the Mozilla environment variable MOZILLA_FIVE_HOME must point + * to the installation directory of Mozilla. + * + * 1. Use the location set by MOZILLA_FIVE_HOME if it is defined + * 2. Parse the file /etc/gre.conf if it is defined. This file is + * set by the RedtHat RPM manager. + * 3. Try some common installation locations. + */ +void fixEnvForMozilla() { + static int fixed = 0; + if (fixed) return; + { + char *ldPath = (char*)getenv("LD_LIBRARY_PATH"); + char *mozillaFiveHome = (char*)getenv("MOZILLA_FIVE_HOME"); + char *grePath = NULL; /* Gecko Runtime Environment Location */ + fixed = 1; + /* Always dup the string so we can free later */ + if (ldPath != NULL) ldPath = strdup(ldPath); + else ldPath = strdup(""); + + /* MOZILLA_FIVE_HOME (if defined) points to the Mozilla + * install directory. Don't look any further if it is set. + */ + if (mozillaFiveHome != NULL) + { + grePath = strdup(mozillaFiveHome); + } + + /* The file gre.conf (if available) points to the + * Mozilla install directory. Don't look any further if + * it is set. + */ + if (grePath == NULL) + { + struct stat buf; + FILE *file = NULL; +#if defined(__amd64__) || defined(__x86_64__) || defined(__powerpc64__) + if (stat("/etc/gre64.conf", &buf) == 0) + { + file = fopen("/etc/gre64.conf", "r"); + } + else if (stat("/etc/gre.d/gre64.conf", &buf) == 0) + { + file = fopen("/etc/gre.d/gre64.conf", "r"); + } else +#endif + if (stat("/etc/gre.conf", &buf) == 0) + { + file = fopen("/etc/gre.conf", "r"); + } + else if (stat("/etc/gre.d/gre.conf", &buf) == 0) + { + file = fopen("/etc/gre.d/gre.conf", "r"); + } + if (file != NULL) + { + char buffer[1024]; + char path[1024]; + while (fgets(buffer, 1024, file) != NULL) + { + if (sscanf(buffer, "GRE_PATH=%s", path) == 1) + { + int index = 0; + char* prefix = prefixes [index]; + while (prefix != NULL) + { + if (strstr(path, prefix)) + { + grePath = strdup(path); + break; + } + prefix = prefixes [++index]; + } + } + } + fclose(file); + } + } + + /* Try some common installation locations. */ + if (grePath == NULL) + { + /* try xulrunner-1*, mozilla-1*, firefox-2/3*, seamonkey-1* directories in /usr/lib/ */ +#if defined(__amd64__) || defined(__x86_64__) || defined(__powerpc64__) + char* dir = "/usr/lib64/"; +#else + char* dir = "/usr/lib/"; +#endif +#if defined (SOLARIS) + char * name = scan(dir); + if (name != NULL) { +#else + struct dirent **namelist; + int i; + int count = scandir(dir, &namelist, filter, alphasort); + if (count > 0) + { + /* count-1 is used below in an attempt to choose XULRunner + * any time one is found + */ + char* name = namelist [count - 1]->d_name; +#endif + grePath = malloc (strlen(dir) + strlen(name) + 1); + strcpy(grePath, dir); + strcat(grePath, name); +#if defined (SOLARIS) + free(name); +#else + for (i = 0; i < count; i++) { + free(namelist [i]); + } + free(namelist); +#endif + } + +#if defined (SOLARIS) + if (grePath == NULL) + { + /* some other typical installation locations */ + char* dirs[] = { + "/usr/sfw/lib/mozilla/", /* Solaris location */ + "/usr/lib/firefox/", /* OpenSolaris location */ + NULL + }; + + /* + * The solaris compiler does not do static linking, so just check + * for a common lib to ensure that the install seems valid. + */ + char* testlib = "libxpcom.so"; + + struct stat buf; + int index = 0; + + char* dir = dirs [index++]; + while (dir != NULL) + { + char* testpath = malloc (strlen(dir) + strlen(testlib) + 1); + strcpy(testpath, dir); + strcat(testpath, testlib); + int success = stat(testpath, &buf) == 0; + free(testpath); + if (success) + { + grePath = strdup(dir); + break; + } + dir = dirs [index++]; + } + } +#endif // SOLARIS + } + + if (grePath != NULL) + { + /* If grePath contains "xulrunner" then do not change the LD_LIBRARY_PATH, + * since it is likely that a xulrunner (not a mozilla or firefox) + * will be found at runtime. Note that MOZILLA_FIVE_HOME is still + * updated if grePath contains "xul" since this variable can act as + * a backup GRE to try if an initially-detected one fails to load. + */ + if (!strstr(grePath, "xulrunner")) { + ldPath = (char*)realloc(ldPath, strlen(ldPath) + strlen(grePath) + 2); + if (strlen(ldPath) > 0) strcat(ldPath, ":"); + strcat(ldPath, grePath); + setenv("LD_LIBRARY_PATH", ldPath, 1); + } + + if (mozillaFiveHome == NULL) setenv("MOZILLA_FIVE_HOME", grePath, 1); + free(grePath); + } + free(ldPath); + } +} +#endif /* MOZILLA_FIX */ diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.h b/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.h new file mode 100644 index 000000000..e227741af --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseMozilla.h @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef ECLIPSE_MOZILLA_H +#define ECLIPSE_MOZILLA_H + +/* Eclipse Mozilla Utility Methods */ + +#ifdef MOZILLA_FIX +extern void fixEnvForMozilla(); +#endif /* MOZILLA_FIX */ + +#endif /* ECLIPSE_MOZILLA_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseNix.c b/features/org.eclipse.equinox.executable.feature/library/eclipseNix.c new file mode 100644 index 000000000..bc57e2250 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseNix.c @@ -0,0 +1,234 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* This file contains code common between GTK & Motif */ +#include "eclipseOS.h" +#include "eclipseCommon.h" +#include "eclipseMozilla.h" +#include "eclipseUtil.h" +#include "eclipseJNI.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#ifdef i386 +#define JAVA_ARCH "i386" +#elif defined(__ppc__) || defined(__powerpc64__) +#define JAVA_ARCH "ppc" +#elif defined(SOLARIS) +#define JAVA_ARCH "sparc" +#elif defined(__amd64__) || defined(__x86_64__) +#define JAVA_ARCH "amd64" +#else +#define JAVA_ARCH DEFAULT_OS_ARCH +#endif + +#ifdef AIX +#define LIB_PATH_VAR _T_ECLIPSE("LIBPATH") +#else +#define LIB_PATH_VAR _T_ECLIPSE("LD_LIBRARY_PATH") +#endif + +#define MAX_LOCATION_LENGTH 40 /* none of the jvmLocations strings should be longer than this */ +static const char* jvmLocations [] = { "j9vm", "../jre/bin/j9vm", + "classic", "../jre/bin/classic", + "../lib/" JAVA_ARCH "/client", + "../lib/" JAVA_ARCH "/server", + "../lib/" JAVA_ARCH "/jrockit", + "../jre/lib/" JAVA_ARCH "/client", + "../jre/lib/" JAVA_ARCH "/server", + "../jre/lib/" JAVA_ARCH "/jrockit", + "../lib/jvm/jre/lib/" JAVA_ARCH "/client", + NULL }; + +static void adjustLibraryPath( char * vmLibrary ); +static char * findLib(char * command); +#ifdef NETSCAPE_FIX +extern void fixEnvForNetscape(); +#endif /* NETSCAPE_FIX */ + +char * findVMLibrary( char* command ) { + char * lib = findLib(command); + if( lib != NULL ) { + adjustLibraryPath(lib); + } + return lib; +} + +static char * findLib(char * command) { + int i; + int pathLength; + struct stat stats; + char * path; /* path to resulting jvm shared library */ + char * location; /* points to begining of jvmLocations section of path */ + + if (command != NULL) { + /*check first to see if command already points to the library */ + if (isVMLibrary(command)) { + if (stat( command, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /* found it */ + return strdup(command); + } + return NULL; + } + + location = strrchr( command, dirSeparator ) + 1; + pathLength = location - command; + path = malloc((pathLength + MAX_LOCATION_LENGTH + 1 + strlen(vmLibrary) + 1) * sizeof(char)); + strncpy(path, command, pathLength); + location = &path[pathLength]; + + /* + * We are trying base/jvmLocations[*]/vmLibrary + * where base is the directory containing the given java command, normally jre/bin + */ + i = -1; + while(jvmLocations[++i] != NULL) { + sprintf(location, "%s%c%s", jvmLocations[i], dirSeparator, vmLibrary); + if (stat( path, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /* found it */ + return path; + } + } + } + return NULL; +} + +/* adjust the LD_LIBRARY_PATH for the vmLibrary */ +static void adjustLibraryPath( char * vmLibrary ) { + char * c; + char * ldPath; + char * newPath; + int i; + int numPaths = 0; + int length = 0; + int needAdjust = 0; + + char ** paths = NULL; +#ifdef MOZILLA_FIX + fixEnvForMozilla(); +#endif /* MOZILLA_FIX */ +#ifdef NETSCAPE_FIX + fixEnvForNetscape(); +#endif /* NETSCAPE_FIX */ + + paths = getVMLibrarySearchPath(vmLibrary); + + ldPath = (char*)getenv(LIB_PATH_VAR); + if (!ldPath) { + ldPath = _T_ECLIPSE(""); + needAdjust = 1; + } else { + needAdjust = !containsPaths(ldPath, paths); + } + if (!needAdjust) { + for (i = 0; paths[i] != NULL; i++) + free(paths[i]); + free(paths); + return; + } + + /* set the value for LD_LIBRARY_PATH */ + length = strlen(ldPath); + c = concatStrings(paths); + newPath = malloc((_tcslen(c) + length + 1) * sizeof(_TCHAR)); + _stprintf(newPath, _T_ECLIPSE("%s%s"), c, ldPath); + + setenv( LIB_PATH_VAR, newPath, 1); + free(newPath); + free(c); + + for (i = 0; i < numPaths; i++) + free(paths[i]); + free(paths); + + /* now we must restart for this to take affect */ + restartLauncher(initialArgv[0], initialArgv); +} + +void restartLauncher( char* program, char* args[] ) +{ + /* just restart in-place */ + execvp( program != NULL ? program : args[0], args); +} + +void processVMArgs(_TCHAR **vmargs[] ) { + /* nothing yet */ +} + +JavaResults* startJavaVM( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ) +{ + return startJavaJNI(libPath, vmArgs, progArgs, jarFile); +} + +int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ) { + int descriptors[2]; + int result = 0; + int pid = -1; + + if (javaVM == NULL) + return 0; + + /* create pipe, [0] is read end, [1] is write end */ + if (pipe(descriptors) != 0) + return 0; /* error */ + + pid = fork(); + if (pid == 0 ) { + /* child, connect stdout & stderr to write end of the pipe*/ + dup2(descriptors[1], STDERR_FILENO); + dup2(descriptors[1], STDOUT_FILENO); + + /* close descriptors */ + close(descriptors[0]); + close(descriptors[1]); + + { + /* exec java -version */ + _TCHAR *args [] = { javaVM, _T_ECLIPSE("-version"), NULL }; + execv(args[0], args); + /* if we make it here, there was a problem with exec, just exit */ + exit(0); + } + } else if (pid > 0){ + /* parent */ + FILE * stream = NULL; + int status = 0; + close(descriptors[1]); + stream = fdopen( descriptors[0], "r"); + if (stream != NULL) { + _TCHAR buffer[256]; + while ( fgets(buffer, 256, stream) != NULL) { + if (_tcsstr(buffer, _T_ECLIPSE("Java HotSpot(TM)")) || _tcsstr(buffer, _T_ECLIPSE("OpenJDK"))) { + result = 1; + break; + } + if (_tcsstr(buffer, _T_ECLIPSE("IBM")) != NULL) { + result = 0; + break; + } + } + fclose(stream); + close(descriptors[0]); + } + waitpid(pid, &status, 0); + } else { + /* failed to fork */ + close(descriptors[0]); + close(descriptors[1]); + } + return result; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseOS.h b/features/org.eclipse.equinox.executable.feature/library/eclipseOS.h new file mode 100644 index 000000000..a0e0902d1 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseOS.h @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + *******************************************************************************/ + +#ifndef ECLIPSE_OS_H +#define ECLIPSE_OS_H + +#include "eclipseJNI.h" +#include "eclipseUnicode.h" + +#ifdef MACOSX +#define JAVA_FRAMEWORK "/System/Library/Frameworks/JavaVM.framework" +#endif + +/* Operating System Dependent Information */ + +/*** See eclipse.c for information on the launcher runtime architecture ***/ + +/* Global Variables */ +extern _TCHAR* defaultVM; /* name of VM to use normally */ +#ifdef _WIN32 +extern _TCHAR* consoleVM; /* windows needs a different vm executable for the console */ +#endif +extern _TCHAR* shippedVMDir; /* VM bin directory with separator */ +extern _TCHAR* exitData; /* exit data set from Java */ +extern _TCHAR* vmLibrary; /* name of the VM shared library */ +extern int initialArgc; /* argc originally used to start launcher */ +extern _TCHAR** initialArgv; /* argv originally used to start launcher */ +extern _TCHAR* eeLibPath; /* library path specified in a .ee file */ +extern int secondThread; /* whether or not to start the vm on a second thread */ + +/* OS Specific Functions */ + +/** Display a Message + * + * This method is called to display a message to the user. + * The method should not return until the user has acknowledged + * the message. This method will only be called after the window + * system has been initialized. + */ +extern void displayMessage( _TCHAR* title, _TCHAR* message ); + + +/** Initialize the Window System + * + * This method is called after the command line arguments have been + * parsed. Its purpose is to initialize the corresponding window system. + * + * The showSplash flag indicates the splash window will be displayed by + * this process (e.g., value will be zero for the main launcher). + */ +extern int initWindowSystem( int* argc, _TCHAR* argv[], int showSplash ); + + +/** Show the Splash Window + * + * This method is called to display the actual splash window. It will only + * be called by the splash window process and not the main launcher process. + * The splash ID passed corresponds to the string returned from initWindowSystem(). + * If possible, this ID should be used to communicate some piece of data back + * to the main launcher program for two reasons: + * 1) to detect when the splash window process terminates + * 2) to terminate the splash window process should the JVM terminate before it + * completes its initialization. + * + * Two parameters are passed: the install home directory and a specific bitmap image + * file for a feature. The feature's image file is tried first and if it cannot be + * displayed, the images from the install directory are used. + * + * Return (exit code): + * 0 - success + * non-zero - could not find a splash image to display + */ +extern int showSplash( const _TCHAR* featureImage ); + +/** Get List of Java VM Arguments + * + * A given Java VM might require a special set of arguments in order to + * optimize its performance. This method returns a NULL terminated array + * of strings, where each string is a separate VM argument. + */ +extern _TCHAR** getArgVM( _TCHAR *vm ); + +/* Find the vm shared library associated with the given java executable */ +extern _TCHAR * findVMLibrary( _TCHAR * command ); + +extern void dispatchMessages(); + +extern jlong getSplashHandle(); + +extern void takeDownSplash(); + +extern void restartLauncher( _TCHAR* program, _TCHAR* args[] ); + +/* launch the vm in a separate process and wait for it to finish */ +extern JavaResults* launchJavaVM( _TCHAR* args[] ); + +/* launch the vm in this process using JNI invocation */ +extern JavaResults* startJavaVM( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ); + +/* do any platform specific processing of the user vmargs */ +extern void processVMArgs(_TCHAR **vmargs[] ); + +/* is this a Sun VM, returns 0 if we don't know */ +extern int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ); + +/* an array of paths that will need to be on the search path to load the vm shared library */ +extern _TCHAR ** getVMLibrarySearchPath(_TCHAR * vmLibrary); + +extern int reuseWorkbench(_TCHAR** filePath, int timeout); + +#endif /* ECLIPSE_OS_H */ + diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseShm.c b/features/org.eclipse.equinox.executable.feature/library/eclipseShm.c new file mode 100644 index 000000000..e46c1f5bc --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseShm.c @@ -0,0 +1,273 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Silenio Quarti + *******************************************************************************/ + +#include "eclipseOS.h" +#include "eclipseShm.h" + +static _TCHAR* ECLIPSE_UNITIALIZED = _T_ECLIPSE("ECLIPSE_UNINITIALIZED"); + +#ifdef _WIN32 + +#include <stdio.h> + +#ifdef __MINGW32__ +#include <stdlib.h> +#endif + +int createSharedData(_TCHAR** id, int size) { + HANDLE mapHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL); + if (mapHandle == 0) return -1; + if (id != NULL) { + *id = malloc(18 * sizeof(_TCHAR)); +#ifdef WIN64 + _stprintf(*id, _T_ECLIPSE("%lx_%lx"), GetCurrentProcessId(), (DWORDLONG) mapHandle); +#else + _stprintf(*id, _T_ECLIPSE("%lx_%lx"), GetCurrentProcessId(), (DWORD) mapHandle); +#endif + } + /* set the shared data to "uninitialized" */ + setSharedData(*id, ECLIPSE_UNITIALIZED); + return 0; +} + +static int getShmID(const _TCHAR* id, LPDWORD processID, LPHANDLE handle) { + if (id != NULL && _tcslen(id) > 0) { + DWORD i1; +#ifdef WIN64 + DWORDLONG i2; +#else + DWORD i2; +#endif + if (_stscanf(id, _T_ECLIPSE("%lx_%lx"), &i1, &i2) != 2) return -1; + *processID = (DWORD)i1; + *handle = (HANDLE)i2; + return 0; + } + return -1; +} + +int destroySharedData(_TCHAR* id) { + DWORD processID; + HANDLE handle; + if (getShmID(id, &processID, &handle) == -1) return -1; + if (!CloseHandle(handle)) return -1; + return 0; +} + +int getSharedData(_TCHAR* id, _TCHAR** data) { + _TCHAR *sharedData, *newData = NULL; + DWORD processID; + HANDLE handle, mapHandle = NULL, processHandle; + if (getShmID(id, &processID, &handle) == -1) return -1; + if (processID == GetCurrentProcessId()) { + mapHandle = handle; + } else { + processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID); + if (processHandle == NULL) return -1; + DuplicateHandle(processHandle, handle, GetCurrentProcess(), &mapHandle, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS); + CloseHandle(processHandle); + } + if (mapHandle == NULL) return -1; + sharedData = MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0); + if (sharedData == NULL) return -1; + if (_tcscmp(sharedData, ECLIPSE_UNITIALIZED)== 0) return 0; + if (data != NULL) { + size_t length = (_tcslen(sharedData) + 1) * sizeof(_TCHAR); + newData = malloc(length); + memcpy(newData, sharedData, length); + } + if (!UnmapViewOfFile(sharedData)) { + free(newData); + return -1; + } + if (handle != mapHandle) { + CloseHandle(mapHandle); + } + *data = newData; + return 0; +} + +int setSharedData(const _TCHAR* id, const _TCHAR* data) { + _TCHAR* sharedData; + DWORD processID; + HANDLE handle, mapHandle = NULL, processHandle; + if (getShmID(id, &processID, &handle) == -1) return -1; + if (processID == GetCurrentProcessId()) { + mapHandle = handle; + } else { + processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID); + if (processHandle == NULL) return -1; + DuplicateHandle(processHandle, handle, GetCurrentProcess(), &mapHandle, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS); + CloseHandle(processHandle); + } + if (mapHandle == NULL) return -1; + sharedData = MapViewOfFile(mapHandle, FILE_MAP_WRITE, 0, 0, 0); + if (sharedData == NULL) return -1; + if (data != NULL) { + size_t length = (_tcslen(data) + 1) * sizeof(_TCHAR); + memcpy(sharedData, data, length); + } else { + memset(sharedData, 0, sizeof(_TCHAR)); + } + if (!UnmapViewOfFile(sharedData)) { + return -1; + } + if (handle != mapHandle) { + CloseHandle(mapHandle); + } + return 0; +} + +#elif PHOTON + +#include <fcntl.h> +#include <sys/mman.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +int createSharedData(char** id, int size) { + int fd; + char* location = "/tmp/eclipse_%x"; + char* name = malloc(strlen(location) + 9); + sprintf(name, location, getpid()); + if ((fd = shm_open(name, O_RDWR | O_CREAT, 0666 )) == -1) return -1; + if (ftruncate(fd, size) == -1 ) { + shm_unlink(name); + return -1; + } + close( fd ); + if (id != NULL) { + *id = name; + } + return 0; +} + +int destroySharedData(char* id) { + return shm_unlink(id); +} + +int getSharedData(char* id, char** data) { + int fd, length, size; + char *sharedData, *newData = NULL; + if ((fd = shm_open(id, O_RDWR, 0666 )) == -1) return -1; + size = lseek(fd, 0, SEEK_END); + sharedData = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); + if (sharedData != MAP_FAILED) { + if (data != NULL) { + length = strlen(sharedData) + 1; + newData = malloc(length); + memcpy(newData, sharedData, length); + } + munmap(sharedData, size); + } + close(fd); + *data = newData; + return newData == NULL ? -1 : 0; +} + +int setSharedData(char* id, char* data) { + int fd, length, size; + char *sharedData; + if ((fd = shm_open(id, O_RDWR, 0666 )) == -1) return -1; + size = lseek(fd, 0, SEEK_END); + sharedData = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); + if (sharedData != MAP_FAILED) { + if (data != NULL) { + length = strlen(data) + 1; + memcpy(sharedData, data, length); + } else { + memset(sharedData, 0, sizeof(char)); + } + munmap(sharedData, size); + } + close(fd); + return 0; +} + +#else /* Unix like platforms */ + +#include <sys/shm.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +int createSharedData(char** id, int size) { + int shmid; + key_t key = getpid(); + if ((shmid = shmget(key, size, IPC_CREAT | 0666)) < 0) { + return -1; + } + if (id != NULL) { + *id = malloc(9 * sizeof(char)); + sprintf(*id, "%x", shmid); + } + setSharedData(*id, ECLIPSE_UNITIALIZED); + return 0; +} + +static int getShmID(const char* id) { + int shmid = -1; + /* Determine the shared memory id. */ + if (id != NULL && strlen(id) > 0) { + sscanf(id, "%x", &shmid); + } + return shmid; +} + +int destroySharedData(char* id) { + int shmid = getShmID(id); + if (shmid == -1) return -1; + return shmctl(shmid, IPC_RMID, NULL); +} + +int getSharedData( char* id, char** data ) { + char *sharedData, *newData = NULL; + int length; + int shmid = getShmID(id); + if (shmid == -1) return -1; + sharedData = shmat(shmid, (void *)0, 0); + if (sharedData == (char *)(-1)) return -1; + if (_tcscmp(sharedData, ECLIPSE_UNITIALIZED) == 0) return 0; + length = strlen(sharedData) + 1; + newData = malloc(length); + memcpy(newData, sharedData, length); + if (shmdt(sharedData) != 0) { + free(newData); + return -1; + } + *data = newData; + return 0; +} + +int setSharedData(const char* id, const char* data) { + char* sharedData; + int length; + int shmid = getShmID(id); + if (shmid == -1) return -1; + sharedData = shmat(shmid, (void *)0, 0); + if (sharedData == (char *)(-1)) return -1; + if (data != NULL) { + length = strlen(data) + 1; + memcpy(sharedData, data, length); + } else { + memset(sharedData, 0, sizeof(char)); + } + if (shmdt(sharedData) != 0) { + return -1; + } + return 0; +} + +#endif /* Unix like platforms */ diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseShm.h b/features/org.eclipse.equinox.executable.feature/library/eclipseShm.h new file mode 100644 index 000000000..9cac1aa34 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseShm.h @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Silenio Quarti + *******************************************************************************/ + +#ifndef ECLIPSE_SHM_H +#define ECLIPSE_SHM_H + +/* Shared memory utilities */ + +/** + * Creates and initializes a shared memory segment + * with the specified size in bytes. The id for the + * shared memory segment is stored in the id argument + * and can be used from any process. It must be freed + * with free(). + * + * Returns 0 if success. + */ +extern int createSharedData(_TCHAR** id, int size); + +/** + * Destroy the shared memory segment specified by the + * id argument. The id is the same as the one return + * by createSharedData(). This function must be called + * by the same process that created the segment. + * + * Returns 0 if success. + */ +extern int destroySharedData(_TCHAR* id); + +/** + * Gets a copy of the shared memory segment specified + * by the id argument. The copy is stored in the data + * argument as a null terminated string and must be + * freed by free(). + * + * Returns 0 if success. + */ +extern int getSharedData(_TCHAR* id, _TCHAR** data); + +/** + * Sets the shared memory segment specified by the id + * argument with a null terminated string specified by + * data. + * + * Returns 0 if sucess. + */ +extern int setSharedData(const _TCHAR* id, const _TCHAR* data); + +#endif /* ECLIPSE_SHM_H */ + + diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseUnicode.h b/features/org.eclipse.equinox.executable.feature/library/eclipseUnicode.h new file mode 100644 index 000000000..f98b77dc7 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseUnicode.h @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Silenio Quarti + *******************************************************************************/ + +#ifndef ECLIPSE_UNICODE_H +#define ECLIPSE_UNICODE_H + +#ifdef _WIN32 + +#ifdef UNICODE +#define _UNICODE +#endif +#include <windows.h> +#include <tchar.h> +#include <ctype.h> + +#ifdef __MINGW32__ +# ifdef UNICODE +# ifndef _TCHAR +# define _TCHAR TCHAR +# endif /* _TCHAR */ +# ifndef _tgetcwd +# define _tgetcwd _wgetcwd +# endif /* _tgetcwd */ +# ifndef _tstat +# define _tstat _wstat +# endif /* _tstat */ +# ifndef _topendir +# define _topendir _wopendir +# endif /* _topendir */ +# ifndef _treaddir +# define _treaddir _wreaddir +# endif /* _treaddir */ +# ifndef _tclosedir +# define _tclosedir _wclosedir +# endif /* _tclosedir */ +# ifndef _tDIR +# define _tDIR _WDIR +# endif /* _tDIR */ +# else /* UNICODE */ +# ifndef _TCHAR +# define _TCHAR char +# endif /* _TCHAR */ +# ifndef _tgetcwd +# define _tgetcwd getcwd +# endif /* _tgetcwd */ +# ifndef _tstat +# define _tstat _stat +# endif /* _tstat */ +# ifndef _topendir +#error message! +# define _topendir opendir +# endif /* _topendir */ +# ifndef _treaddir +# define _treaddir readdir +# endif /* _treaddir */ +# ifndef _tclosedir +# define _tclosedir closedir +# endif /* _tclosedir */ +# ifndef _tDIR +# define _tDIR DIR +# endif /* _tDIR */ +# endif /* UNICODE */ +#endif /* __MINGW32__ */ + +#define _T_ECLIPSE _T + +#else /* Platforms other than Windows */ + +#define _TCHAR char +#define _T_ECLIPSE(s) s +#define _fgetts fgets +#define _stat stat +#define _stprintf sprintf +#define _ftprintf fprintf +#define _stscanf sscanf +#define _tcscat strcat +#define _tcschr strchr +#define _tcspbrk strpbrk +#define _tcscmp strcmp +#define _tcscpy strcpy +#define _tcsdup strdup +#define _tcsicmp strcasecmp +#define _tcslen strlen +#define _tcsncpy strncpy +#define _tcsrchr strrchr +#define _tfopen fopen +#define _tgetcwd getcwd +#define _tgetenv getenv +#define _tcstol strtol +#ifndef LINUX +#define _totupper toupper +#endif /* LINUX */ +#define _tprintf printf +#define _tstat stat +#define _tcsncmp strncmp +#define _tcsstr strstr +#define _topendir opendir +#define _treaddir readdir +#define _tclosedir closedir +#define _tDIR DIR +#endif /* _WIN32 */ + +#endif /* ECLIPSE_UNICODE_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.c b/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.c new file mode 100644 index 000000000..130afb347 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.c @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + * Martin Oberhuber (Wind River) - [149994] Add --launcher.appendVmargs + *******************************************************************************/ + +/* Eclipse Launcher Utility Methods */ + +#include "eclipseOS.h" +#include "eclipseCommon.h" +#include "eclipseUtil.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#ifdef _WIN32 +#include <direct.h> +#else +#include <unistd.h> +#include <strings.h> +#endif + +#define MAX_LINE_LENGTH 256 + +/* Is the given VM J9 */ +int isJ9VM( _TCHAR* vm ) +{ + _TCHAR * ch = NULL, *ch2 = NULL; + int res = 0; + + if (vm == NULL) + return 0; + + ch = lastDirSeparator( vm ); + if (isVMLibrary(vm)) { + /* a library, call it j9 if the parent dir is j9vm */ + if(ch == NULL) + return 0; + ch[0] = 0; + ch2 = lastDirSeparator(vm); + if(ch2 != NULL) { + res = (_tcsicmp(ch2 + 1, _T_ECLIPSE("j9vm")) == 0); + } + ch[0] = dirSeparator; + return res; + } else { + if (ch == NULL) + ch = vm; + else + ch++; + return (_tcsicmp( ch, _T_ECLIPSE("j9") ) == 0); + } +} + +int checkProvidedVMType( _TCHAR* vm ) +{ + _TCHAR* ch = NULL; + struct _stat stats; + + if (vm == NULL) return VM_NOTHING; + + if (_tstat(vm, &stats) == 0 && (stats.st_mode & S_IFDIR) != 0) { + /* directory */ + return VM_DIRECTORY; + } + + ch = _tcsrchr( vm, _T_ECLIPSE('.') ); + if(ch == NULL) + return VM_OTHER; + +#ifdef _WIN32 + if (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0) +#else + if ((_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0)) +#endif + { + return VM_LIBRARY; + } + + if (_tcsicmp(ch, _T_ECLIPSE(".ee")) == 0) + return VM_EE_PROPS; + + return VM_OTHER; +} + +/* + * pathList is a pathSeparator separated list of paths, run each through + * checkPath and recombine the results. + * New memory is always allocated for the result + */ +_TCHAR * checkPathList( _TCHAR* pathList, _TCHAR* programDir, int reverseOrder) { + _TCHAR * c1, *c2; + _TCHAR * checked, *result; + size_t checkedLength = 0, resultLength = 0; + size_t bufferLength = _tcslen(pathList); + + result = malloc(bufferLength * sizeof(_TCHAR)); + c1 = pathList; + while (c1 != NULL && *c1 != _T_ECLIPSE('\0')) + { + c2 = _tcschr(c1, pathSeparator); + if (c2 != NULL) + *c2 = 0; + + checked = checkPath(c1, programDir, reverseOrder); + checkedLength = _tcslen(checked); + if (resultLength + checkedLength + 1> bufferLength) { + bufferLength += checkedLength + 1; + result = realloc(result, bufferLength * sizeof(_TCHAR)); + } + + if(resultLength > 0) { + result[resultLength++] = pathSeparator; + result[resultLength] = _T_ECLIPSE('\0'); + } + _tcscpy(result + resultLength, checked); + resultLength += checkedLength; + + if(checked != c1) + free(checked); + if(c2 != NULL) + *(c2++) = pathSeparator; + c1 = c2; + } + + return result; +} + +_TCHAR * concatStrings(_TCHAR**strs) { + return concatPaths(strs, 0); +} + +_TCHAR * concatPaths(_TCHAR** strs, _TCHAR separator) { + _TCHAR separatorString[] = { separator, 0 }; + _TCHAR * result; + int i = -1; + size_t length = 0; + /* first count how large a buffer we need */ + while (strs[++i] != NULL) { + length += _tcslen(strs[i]) + (separator != 0 ? 1 : 0); + } + + result = malloc((length + 1) * sizeof(_TCHAR)); + result[0] = 0; + i = -1; + while (strs[++i] != NULL) { + result = _tcscat(result, strs[i]); + if (separator != 0) + result = _tcscat(result, separatorString); + } + return result; +} + +/* + * Concatenates two NULL-terminated arrays of Strings, + * returning a new NULL-terminated array. + * The returned array must be freed with the regular free(). + */ +_TCHAR** concatArgs(_TCHAR** l1, _TCHAR** l2) { + _TCHAR** newArray = NULL; + int size1 = 0; + int size2 = 0; + + if (l1 != NULL) + while (l1[size1] != NULL) size1++; + if (l2 != NULL) + while (l2[size2] != NULL) size2++; + + newArray = (_TCHAR **) malloc((size1 + size2 + 1) * sizeof(_TCHAR *)); + if (size1 > 0) { + memcpy(newArray, l1, size1 * sizeof(_TCHAR *)); + } + if (size2 > 0) { + memcpy(newArray + size1, l2, size2 * sizeof(_TCHAR *)); + } + newArray[size1 + size2] = NULL; + return newArray; +} + +/* + * returns the relative position of arg in the NULL-terminated list of args, + * or -1 if args does not contain arg. + */ +int indexOf(_TCHAR *arg, _TCHAR **args) { + int i = -1; + if (arg != NULL && args != NULL) { + while (args[++i] != NULL) { + if (_tcsicmp(arg, args[i]) == 0) { + return i; + } + } + } + return -1; +} + +/* + * buffer contains a pathSeparator separated list of paths, check + * that it contains all the paths given. Each path is expected to be + * terminated with a pathSeparator character. + */ +int containsPaths(_TCHAR * str, _TCHAR** paths) { + _TCHAR * buffer; + _TCHAR * c; + int i; + + /* terminate the string with a pathSeparator */ + buffer = malloc((_tcslen(str) + 2) * sizeof(_TCHAR)); + _stprintf(buffer, _T_ECLIPSE("%s%c"), str, pathSeparator); + + for (i = 0; paths[i] != NULL; i++) { + c = _tcsstr(buffer, paths[i]); + if ( c == NULL || !(c == buffer || *(c - 1) == pathSeparator)) + { + /* entry not found */ + free(buffer); + return 0; + } + } + free(buffer); + return 1; +} + +int isVMLibrary( _TCHAR* vm ) +{ + _TCHAR *ch = NULL; + if (vm == NULL) return 0; + ch = _tcsrchr( vm, '.' ); + if(ch == NULL) + return 0; +#ifdef _WIN32 + return (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0); +#else + return (_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0); +#endif +} + +#ifdef AIX + +#include <sys/types.h> +#include <time.h> + +/* Return the JVM version in the format x.x.x + */ +char* getVMVersion( char *vmPath ) +{ + char cmd[MAX_LINE_LENGTH]; + char lineString[MAX_LINE_LENGTH]; + char* firstChar; + char fileName[MAX_LINE_LENGTH]; + time_t curTime; + FILE* fp; + int numChars = 0; + char* version = NULL; + + /* Define a unique filename for the java output. */ + (void) time(&curTime); + (void) sprintf(fileName, "/tmp/tmp%ld.txt", curTime); + + /* Write java -version output to a temp file */ + (void) sprintf(cmd,"%s -version 2> %s", vmPath, fileName); + (void) system(cmd); + + fp = fopen(fileName, "r"); + if (fp != NULL) + { + /* Read java -version output from a temp file */ + if (fgets(lineString, MAX_LINE_LENGTH, fp) == NULL) + lineString[0] = '\0'; + fclose(fp); + unlink(fileName); + + /* Extract version number */ + firstChar = (char *) (strchr(lineString, '"') + 1); + if (firstChar != NULL) + numChars = (int) (strrchr(lineString, '"') - firstChar); + + /* Allocate a buffer and copy the version string into it. */ + if (numChars > 0) + { + version = malloc( numChars + 1 ); + strncpy(version, firstChar, numChars); + version[numChars] = '\0'; + } + } + + return version; +} +#endif /* AIX */ + +/* Compare JVM Versions of the form "x.x.x..." + * + * Returns -1 if ver1 < ver2 + * Returns 0 if ver1 = ver2 + * Returns 1 if ver1 > ver2 + */ +int versionCmp(char *ver1, char *ver2) +{ + char* dot1; + char* dot2; + int num1; + int num2; + + dot1 = strchr(ver1, '.'); + dot2 = strchr(ver2, '.'); + + num1 = atoi(ver1); + num2 = atoi(ver2); + + if (num1 > num2) + return 1; + + if (num1 < num2) + return -1; + + if (dot1 && !dot2) /* x.y > x */ + return 1; + + if (!dot1 && dot2) /* x < x.y */ + return -1; + + if (!dot1 && !dot2) /* x == x */ + return 0; + + return versionCmp((char*)(dot1 + 1), (char*)(dot2 + 1) ); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.h b/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.h new file mode 100644 index 000000000..7843a3f9b --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseUtil.h @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + * Martin Oberhuber (Wind River) - [149994] Add --launcher.appendVmargs + *******************************************************************************/ + +#ifndef ECLIPSE_UTIL_H +#define ECLIPSE_UTIL_H + +/* constants for checkProvidedVMType */ +#define VM_NOTHING 0 /* NULL was given as input */ +#define VM_OTHER 1 /* don't know, could be executable or could be nothing */ +#define VM_DIRECTORY 2 /* it is a directory */ +#define VM_LIBRARY 3 /* it is a library (isVmLibrary would return true) */ +#define VM_EE_PROPS 4 /* it is a vm .ee properties file */ + +/* Eclipse Launcher Utility Methods */ + +/* Is the given Java VM J9 */ +extern int isJ9VM( _TCHAR* vm ); + +/* Is the given file a shared library? */ +extern int isVMLibrary( _TCHAR* vm ); + +/* determine what the provided -vm argument is referring to */ +extern int checkProvidedVMType( _TCHAR* vm ); + +/* take a list of path separated with pathSeparator and run them through checkPath */ +extern _TCHAR * checkPathList( _TCHAR* pathList, _TCHAR* programDir, int reverseOrder); + +/* take a NULL terminated array of strings and concatenate them together into one string */ +extern _TCHAR * concatStrings(_TCHAR** strs); + +/* Concatenates two NULL-terminated arrays of strings into a new array of strings */ +extern _TCHAR** concatArgs(_TCHAR** l1, _TCHAR** l2); + +/* Returns the relative position of arg in the NULL-terminated list of args, or -1 */ +extern int indexOf(_TCHAR *arg, _TCHAR **args); + +/* take a NULL terminated array of strings and concatenate them together using the give pathSeparator */ +extern _TCHAR* concatPaths(_TCHAR** paths, _TCHAR pathSeparator); + +/* check that the buffer contains all the given paths */ +extern int containsPaths(_TCHAR * str, _TCHAR** paths); + +#ifdef AIX +/* Get the version of the VM */ +extern char* getVMVersion( char* vm ); +#endif + +/* Compare JVM Versions */ +extern int versionCmp( char* ver1, char* ver2 ); + +#endif /* ECLIPSE_UTIL_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/.gitignore b/features/org.eclipse.equinox.executable.feature/library/gtk/.gitignore new file mode 100644 index 000000000..8d396827f --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/.gitignore @@ -0,0 +1,3 @@ +/*.o +/eclipse +/eclipse_*.so
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh b/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh new file mode 100644 index 000000000..29d3871cb --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh @@ -0,0 +1,238 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Martin Oberhuber (Wind River) - [176805] Support building with gcc and debug +#******************************************************************************* +# +# Usage: sh build.sh [<optional switches>] [clean] +# +# where the optional switches are: +# -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +# -os <DEFAULT_OS> - default Eclipse "-os" value +# -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value +# -ws <DEFAULT_WS> - default Eclipse "-ws" value +# -java <JAVA_HOME> - java install for jni headers +# +# All other arguments are directly passed to the "make" program. +# This script can also be invoked with the "clean" argument. +# +# Examples: +# sh build.sh clean +# sh build.sh -java /usr/j2se OPTFLAG=-g PICFLAG=-fpic + +cd `dirname $0` + +# Define default values for environment variables used in the makefiles. +programOutput="eclipse" +defaultOS="" +defaultOSArch="" +defaultWS="gtk" +EXEC_DIR=../../../../../rt.equinox.binaries/org.eclipse.equinox.executable +defaultJava=DEFAULT_JAVA_JNI +defaultJavaHome="" +javaHome="" +makefile="" +if [ "${CC}" = "" ]; then + CC=cc + export CC +fi + +# Parse the command line arguments and override the default values. +extraArgs="" +while [ "$1" != "" ]; do + if [ "$1" = "-os" ] && [ "$2" != "" ]; then + defaultOS="$2" + shift + elif [ "$1" = "-arch" ] && [ "$2" != "" ]; then + defaultOSArch="$2" + shift + elif [ "$1" = "-ws" ] && [ "$2" != "" ]; then + defaultWS="$2" + shift + elif [ "$1" = "-output" ] && [ "$2" != "" ]; then + programOutput="$2" + shift + elif [ "$1" = "-java" ] && [ "$2" != "" ]; then + javaHome="$2" + shift + else + extraArgs="$extraArgs $1" + fi + shift +done +if [ "$defaultOS" = "" ]; then + defaultOS=`uname -s` +fi +if [ "$defaultOSArch" = "" ]; then + defaultOSArch=`uname -m` +fi + + +case $defaultOS in + "Linux" | "linux") + makefile="make_linux.mak" + defaultOS="linux" + case $defaultOSArch in + "x86_64") + defaultOSArch="x86_64" + defaultJava=DEFAULT_JAVA_EXEC + [ -d /bluebird/teamswt/swt-builddir/build/JRE/x64/jdk1.6.0_14 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/build/JRE/x64/jdk1.6.0_14" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + i?86 | "x86") + defaultOSArch="x86" + [ -d /bluebird/teamswt/swt-builddir/build/JRE/x32/jdk1.6.0_14 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/build/JRE/x32/jdk1.6.0_14" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "ppc") + defaultOSArch="ppc" + defaultJava=DEFAULT_JAVA_EXEC + [ -d /bluebird/teamswt/swt-builddir/JDKs/PPC/ibm-java2-ppc-50 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/JDKs/PPC/ibm-java2-ppc-50" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "ppc64") + defaultOSArch="ppc64" + defaultJava=DEFAULT_JAVA_EXEC + [ -d /bluebird/teamswt/swt-builddir/JDKs/PPC64/ibm-java2-ppc64-50 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/JDKs/PPC64/ibm-java2-ppc64-50" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "s390") + defaultOSArch="s390" + defaultJava=DEFAULT_JAVA_EXEC + OUTPUT_DIR="$EXEC_DIR/contributed/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "s390x") + defaultOSArch="s390x" + defaultJava=DEFAULT_JAVA_EXEC + OUTPUT_DIR="$EXEC_DIR/contributed/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "ia64") + defaultOSArch="ia64" + defaultJava=DEFAULT_JAVA_EXEC + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + *) + echo "*** Unknown MODEL <${MODEL}>" + ;; + esac + ;; + "AIX" | "aix") + makefile="make_aix.mak" + defaultOS="aix" + if [ -z "$defaultOSArch" ]; then + defaultOSArch="ppc64" + fi + [ -d /bluebird/teamswt/swt-builddir/JDKs/AIX/PPC64/j564/sdk ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/JDKs/AIX/PPC64/j564/sdk" + ;; + "HP-UX" | "hpux") + makefile="make_hpux.mak" + defaultOS="hpux" + case $defaultOSArch in + "ia64_32") + PATH=$PATH:/opt/hp-gcc/bin:/opt/gtk2.6/bin + PKG_CONFIG_PATH="/opt/gtk2.6/lib/pkgconfig" + ;; + "ia64") + PATH=$PATH:/opt/hp-gcc/bin:/opt/gtk_64bit/bin + PKG_CONFIG_PATH="/opt/gtk_64bit/lib/hpux64/pkgconfig" + ;; + esac + export PATH PKG_CONFIG_PATH + [ -d /opt/java1.5 ] && defaultJavaHome="/opt/java1.5" + ;; + "SunOS" | "solaris") + makefile="make_solaris.mak" + defaultOS="solaris" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + #PATH=/usr/ccs/bin:/opt/SUNWspro/bin:$PATH + PATH=/usr/ccs/bin:/export/home/SUNWspro/bin:$PATH + export PATH + if [ "$PROC" = "" ]; then + PROC=`uname -p` + fi + case ${PROC} in + "i386" | "x86") + defaultOSArch="x86" + [ -d /bluebird/teamswt/swt-builddir/build/JRE/Solaris_x86/jdk1.6.0_14 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/build/JRE/Solaris_x86/jdk1.6.0_14" + CC=cc + ;; + "sparc") + defaultOSArch="sparc" + [ -d /bluebird/teamswt/swt-builddir/build/JRE/SPARC/jdk1.6.0_14 ] && defaultJavaHome="/bluebird/teamswt/swt-builddir/build/JRE/SPARC/jdk1.6.0_14" + CC=cc + ;; + *) + echo "*** Unknown processor type <${PROC}>" + ;; + esac + ;; + *) + echo "Unknown OS -- build aborted" + ;; +esac +export CC + + +# Set up environment variables needed by the makefiles. +PROGRAM_OUTPUT="$programOutput" +DEFAULT_OS="$defaultOS" +DEFAULT_OS_ARCH="$defaultOSArch" +DEFAULT_WS="$defaultWS" +DEFAULT_JAVA=$defaultJava + +origJavaHome=$JAVA_HOME +if [ -n "$javaHome" ]; then + JAVA_HOME=$javaHome + export JAVA_HOME +elif [ -z "$JAVA_HOME" -a -n "$defaultJavaHome" ]; then + JAVA_HOME="$defaultJavaHome" + export JAVA_HOME +fi + +if [ "$defaultOSArch" = "ppc64" ]; then + if [ "$defaultOS" = "aix" ]; then + M_ARCH=-maix64 + else + M_ARCH=-m64 + fi + export M_ARCH +elif [ "$defaultOSArch" = "s390" ]; then + M_ARCH=-m31 + export M_ARCH +elif [ "$defaultOSArch" = "ia64" ]; then + M_ARCH=-mlp64 + export M_ARCH +fi + +LIBRARY_DIR="$EXEC_DIR/../org.eclipse.equinox.launcher.$defaultWS.$defaultOS.$defaultOSArch" +OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + +export OUTPUT_DIR PROGRAM_OUTPUT DEFAULT_OS DEFAULT_OS_ARCH DEFAULT_WS DEFAULT_JAVA LIBRARY_DIR + +# If the OS is supported (a makefile exists) +if [ "$makefile" != "" ]; then + if [ "$extraArgs" != "" ]; then + make -f $makefile $extraArgs + else + echo "Building $OS launcher. Defaults: -os $DEFAULT_OS -arch $DEFAULT_OS_ARCH -ws $DEFAULT_WS" + make -f $makefile clean + case x$CC in + x*gcc*) make -f $makefile all PICFLAG=-fpic ;; + *) make -f $makefile all ;; + esac + fi +else + echo "Unknown OS $OS -- build aborted" +fi + +#restore original JAVA_HOME +JAVA_HOME="$origJavaHome" +export JAVA_HOME diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/build.xml b/features/org.eclipse.equinox.executable.feature/library/gtk/build.xml new file mode 100644 index 000000000..f485479d3 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/build.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="install"/> + </exec> +</target> + +<target name="build_eclipse_ppc"> + <exec dir="." executable="sh"> + <env key="MODEL" value="ppc"/> + <arg line="${basedir}/build.sh"/> + <arg line="install"/> + </exec> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.c b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.c new file mode 100644 index 000000000..6ec48e79f --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.c @@ -0,0 +1,347 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + * Tom Tromey (Red Hat, Inc.) + *******************************************************************************/ + +#include "eclipseMozilla.h" +#include "eclipseCommon.h" +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include "eclipseGtk.h" + +#include <signal.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <dlfcn.h> +#ifdef SOLARIS +#include <sys/filio.h> +#endif +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <semaphore.h> +#include <fcntl.h> + +#ifdef HPUX +#define SEM_FAILED (void *)-1 +#endif + +/* Global Variables */ +char* defaultVM = "java"; +char* vmLibrary = "libjvm.so"; +char* shippedVMDir = "jre/bin/"; + +/* Define the special arguments for the various Java VMs. */ +static char* argVM_JAVA[] = { NULL }; + +/* Define local variables . */ +static long splashHandle = 0; +static GtkWidget* shellHandle = 0; + +static sem_t* mutex; +static Atom appWindowAtom, launcherWindowAtom; +static _TCHAR** openFilePath = NULL; /* the files we want to open */ +static int openFileTimeout = 60; /* number of seconds to wait before timeout */ +static int windowPropertySet = 0; /* set to 1 on success */ + +static struct sigaction quitAction; +static struct sigaction intAction; + +/* Local functions */ +static void catch_signal(int sig) { + //catch signals, free the lock, reinstall the original + //signal handlers and reraise the signal. + sem_post(mutex); + sem_close(mutex); + sigaction(SIGINT, &intAction, NULL); + sigaction(SIGQUIT, &intAction, NULL); + raise(sig); +} + +typedef int (*LockFunc)(); +int executeWithLock(char *name, LockFunc func) { + int result = -1; + int lock = -1; + struct sigaction action; + + mutex = sem_open(name, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 1); + if (mutex == SEM_FAILED) { + //create failed. Probably lock is already created so try opening the existing lock. + mutex = sem_open(name, 0); + } + if (mutex == SEM_FAILED) + return -1; //this is an error. + + // install signal handler to free the lock if something bad happens. + // sem_t is not freed automatically when a process ends. + action.sa_handler = catch_signal; + sigaction(SIGINT, &action, &intAction); + sigaction(SIGQUIT, &action, &quitAction); + + while ((lock = sem_trywait(mutex)) != 0) { + if (errno == EAGAIN) { + //couldn't acquire lock, sleep a bit and try again + sleep(1); + if (--openFileTimeout > 0) + continue; + } + break; + } + + if (lock == 0) + result = func(); + + sem_post(mutex); + sem_close(mutex); + + //reinstall the original signal handlers + sigaction(SIGINT, &intAction, NULL); + sigaction(SIGQUIT, &quitAction, NULL); + return result; +} + +/* Create a "SWT_Window_" + APP_NAME string with optional suffix. + * Caller should free the memory when finished */ +static char * createSWTWindowString(char * suffix, int semaphore) { +#ifdef SOLARIS + /* solaris requires semaphore names to start with '/' */ + char * prefix = semaphore != 0 ? _T_ECLIPSE("/SWT_Window_") : _T_ECLIPSE("SWT_Window_"); +#else + char * prefix = _T_ECLIPSE("SWT_Window_"); +#endif + + char * result = malloc((_tcslen(prefix) + _tcslen(getOfficialName()) + (suffix != NULL ? _tcslen(suffix) : 0) + 1) * sizeof(char)); + if (suffix != NULL) + _stprintf(result, _T_ECLIPSE("%s%s%s"), prefix, getOfficialName(), suffix); + else + _stprintf(result, _T_ECLIPSE("%s%s"), prefix, getOfficialName()); + return result; +} + +static int setAppWindowPropertyFn() { + Window appWindow; + Atom propAtom; + _TCHAR *propVal; + + //Look for the SWT window. If it's there, set a property on it. + appWindow = gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, appWindowAtom); + if (appWindow) { + propAtom = gtk.XInternAtom(gtk_GDK_DISPLAY, "org.eclipse.swt.filePath.message", FALSE); + //append a colon delimiter in case more than one file gets appended to the app windows property. + propVal = concatPaths(openFilePath, _T_ECLIPSE(':')); + gtk.XChangeProperty(gtk_GDK_DISPLAY, appWindow, propAtom, propAtom, 8, PropModeAppend, (unsigned char *)propVal, _tcslen(propVal)); + free(propVal); + windowPropertySet = 1; + return 1; + } + return 0; +} + +/* set the Application window property by executing _setWindowPropertyFn within a semaphore */ +int setAppWindowProperty() { + int result; + char * mutexName = createSWTWindowString(NULL, 1); + result = executeWithLock(mutexName, setAppWindowPropertyFn); + gtk.XSync(gtk_GDK_DISPLAY, False); + free(mutexName); + return result; +} + +/* timer callback function to call setAppWindowProperty */ +static gboolean setAppWindowTimerProc(gpointer data) { + //try to set the app window property. If unsuccessful return true to reschedule the timer. + openFileTimeout--; + return !setAppWindowProperty() && openFileTimeout > 0; +} + +int createLauncherWindow() { + Window window, launcherWindow; + //check if a launcher window exists. If none exists, we know we are the first and we should be launching the app. + window = gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom); + if (window == 0) { + //create a launcher window that other processes can find. + launcherWindow = gtk.XCreateWindow(gtk_GDK_DISPLAY, gtk.XRootWindow(gtk_GDK_DISPLAY, gtk.XDefaultScreen(gtk_GDK_DISPLAY)), -10, -10, 1, + 1, 0, 0, InputOnly, CopyFromParent, (unsigned long) 0, (XSetWindowAttributes *) NULL); + //for some reason Set and Get are both necessary. Set alone does nothing. + gtk.XSetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom, launcherWindow, CurrentTime); + gtk.XGetSelectionOwner(gtk_GDK_DISPLAY, launcherWindowAtom); + //add a timeout to set the property on the apps window once the app is launched. + gtk.g_timeout_add(1000, setAppWindowTimerProc, 0); + return 0; + } + return 1; +} + +int reuseWorkbench(_TCHAR** filePath, int timeout) { + char *appName, *launcherName; + int result = 0; + + if (initWindowSystem(&initialArgc, initialArgv, 1) != 0) + return -1; + + openFileTimeout = timeout; + openFilePath = filePath; + + //App name is defined in SWT as well. Values must be consistent. + appName = createSWTWindowString(NULL, 0); + appWindowAtom = gtk.XInternAtom(gtk_GDK_DISPLAY, appName, FALSE); + free(appName); + + //check if app is already running. Just set property if it is. + if (setAppWindowProperty() > 0) + return 1; + + /* app is not running, create a launcher window to act as a mutex so we don't need to keep the semaphore locked */ + launcherName = createSWTWindowString(_T_ECLIPSE("_Launcher"), 1); + launcherWindowAtom = gtk.XInternAtom(gtk_GDK_DISPLAY, launcherName, FALSE); + result = executeWithLock(launcherName, createLauncherWindow); + free(launcherName); + + if (result == 1) { + //The app is already being launched in another process. Set the property on that app window and exit + while (openFileTimeout > 0) { + if (setAppWindowProperty() > 0) + return 1; //success + else { + openFileTimeout--; + sleep(1); + } + } + //timed out trying to set the app property + result = 0; + } + return result; +} + +/* Create and Display the Splash Window */ +int showSplash( const char* featureImage ) +{ + GtkWidget *image; + GdkPixbuf *pixbuf; + + if (splashHandle != 0) + return 0; /* already showing splash */ + if (featureImage == NULL) + return -1; + + if (initialArgv == NULL) + initialArgc = 0; + + if( initWindowSystem(&initialArgc, initialArgv, 1) != 0) + return -1; + + shellHandle = gtk.gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk.gtk_window_set_decorated((GtkWindow*)(shellHandle), FALSE); + gtk.g_signal_connect_data((gpointer)shellHandle, "destroy", (GtkSignalFunc)(gtk.gtk_widget_destroyed), &shellHandle, NULL, 0); + + pixbuf = gtk.gdk_pixbuf_new_from_file(featureImage, NULL); + image = gtk.gtk_image_new_from_pixbuf(pixbuf); + if (pixbuf) { + gtk.g_object_unref(pixbuf); + } + gtk.gtk_container_add((GtkContainer*)(shellHandle), image); + + if (getOfficialName() != NULL) + gtk.gtk_window_set_title((GtkWindow*)(shellHandle), getOfficialName()); + gtk.gtk_window_set_position((GtkWindow*)(shellHandle), GTK_WIN_POS_CENTER); + gtk.gtk_window_resize((GtkWindow*)(shellHandle), gtk.gdk_pixbuf_get_width(pixbuf), gtk.gdk_pixbuf_get_height(pixbuf)); + gtk.gtk_widget_show_all((GtkWidget*)(shellHandle)); + splashHandle = (long)shellHandle; + dispatchMessages(); + return 0; +} + +void dispatchMessages() { + if (gtk.g_main_context_iteration != 0) + while(gtk.g_main_context_iteration(0,0) != 0) {} +} + +jlong getSplashHandle() { + return splashHandle; +} + +void takeDownSplash() { + if(shellHandle != 0) { + gtk.gtk_widget_destroy(shellHandle); + dispatchMessages(); + splashHandle = 0; + shellHandle = NULL; + } +} + +/* Get the window system specific VM arguments */ +char** getArgVM( char* vm ) +{ + char** result; + +/* if (isJ9VM( vm )) + return argVM_J9;*/ + + /* Use the default arguments for a standard Java VM */ + result = argVM_JAVA; + return result; +} + +JavaResults* launchJavaVM( char* args[] ) +{ + JavaResults* jvmResults = NULL; + pid_t jvmProcess, finishedProcess = 0; + int exitCode; + +#ifdef MOZILLA_FIX + fixEnvForMozilla(); +#endif /* MOZILLA_FIX */ + + jvmProcess = fork(); + if (jvmProcess == 0) + { + /* Child process ... start the JVM */ + execv(args[0], args); + + /* The JVM would not start ... return error code to parent process. */ + /* TODO, how to distinguish this as a launch problem to the other process? */ + _exit(errno); + } + + jvmResults = malloc(sizeof(JavaResults)); + memset(jvmResults, 0, sizeof(JavaResults)); + + /* If the JVM is still running, wait for it to terminate. */ + if (jvmProcess != 0) + { + /* When attempting a file open, we need to spin the event loop + * for setAppWindowTimerProc to run. When that succeeds or times out, + * we can stop the event loop and just wait on the child process. + */ + if (openFilePath != NULL) { + struct timespec sleepTime; + sleepTime.tv_sec = 0; + sleepTime.tv_nsec = 5e+8; // 500 milliseconds + + while(openFileTimeout > 0 && !windowPropertySet && (finishedProcess = waitpid(jvmProcess, &exitCode, WNOHANG)) == 0) { + dispatchMessages(); + nanosleep(&sleepTime, NULL); + } + } + if (finishedProcess == 0) + waitpid(jvmProcess, &exitCode, 0); + if (WIFEXITED(exitCode)) + /* TODO, this should really be a runResult if we could distinguish the launch problem above */ + jvmResults->launchResult = WEXITSTATUS(exitCode); + } + + return jvmResults; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.h b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.h new file mode 100644 index 000000000..503c9a5f9 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtk.h @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +#ifndef ECLIPSE_GTK_H +#define ECLIPSE_GTK_H + +#include <gtk/gtk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk/gdkx.h> + +struct GTK_PTRS { + short not_initialized; + void (*gtk_container_add) (GtkContainer*, GtkWidget*); + gint (*gtk_dialog_run) (GtkDialog *); + GtkWidget* (*gtk_image_new_from_pixbuf)(GdkPixbuf*); + gboolean (*gtk_init_check) (int*, char***); + gboolean (*gtk_init_with_args) (int*, char***, const char *, void *, const char *, GError **); + GtkWidget* (*gtk_message_dialog_new) (GtkWindow*, GtkDialogFlags, GtkMessageType, GtkButtonsType, const gchar*, ...); + gchar* (*gtk_set_locale) (); + void (*gtk_widget_destroy) (GtkWidget*); + void (*gtk_widget_destroyed) (GtkWidget*, GtkWidget**); + void (*gtk_widget_show_all) (GtkWidget*); + GtkWidget* (*gtk_window_new) (GtkWindowType); + void (*gtk_window_resize) (GtkWindow*, gint, gint); + void (*gtk_window_set_title) (GtkWindow*, const gchar*); + void (*gtk_window_set_decorated) (GtkWindow*, gboolean); + void (*gtk_window_set_position) (GtkWindow*, GtkWindowPosition); + + gulong (*g_signal_connect_data) (gpointer, const gchar*, GCallback, gpointer, GClosureNotify, GConnectFlags); + gboolean (*g_main_context_iteration) (GMainContext*, gboolean); + void (*g_object_unref) (gpointer); + GObject* (*g_object_new) (GType, const gchar*, ...); + guint (*g_timeout_add) (guint, GSourceFunc, gpointer); + void (*g_error_free) (GError *); + +#ifdef SOLARIS + GString* (*g_string_insert_c) (GString *, gssize, gchar); +#endif + + GdkDisplay* (*gdk_display_get_default) (); + Display* (*gdk_x11_display_get_xdisplay) (GdkDisplay*); + GdkPixbuf* (*gdk_pixbuf_new_from_file) (const char*, GError **); + int (*gdk_pixbuf_get_width) (const GdkPixbuf*); + int (*gdk_pixbuf_get_height) (const GdkPixbuf*); + void (*gdk_set_program_class) (const char*); + + Window (*XGetSelectionOwner) (Display*, Atom); + void (*XSetSelectionOwner) (Display*, Atom, Window, Time); + void (*XChangeProperty) (Display*, Window, Atom, Atom, int, int, unsigned char *, int); + Window (*XCreateWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual*, unsigned long, XSetWindowAttributes*); + void (*XSync) (Display*, Bool); + int (*XDefaultScreen) (Display*); + Window (*XRootWindow) (Display*, int); + Atom (*XInternAtom) (Display*, _Xconst char*, Bool ); +}; + +#define gtk_GDK_DISPLAY gtk.gdk_x11_display_get_xdisplay(gtk.gdk_display_get_default()) +extern struct GTK_PTRS gtk; + +#define FN_TABLE_ENTRY(fn, required) { (void**)& gtk.fn, #fn, required } +typedef struct { + void ** fnPtr; + char * fnName; + int required; +} FN_TABLE; + +/* load the gtk libraries and initialize the function pointers */ +extern int loadGtk(); + +#endif diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkCommon.c b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkCommon.c new file mode 100644 index 000000000..b30327ec5 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkCommon.c @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseCommon.h" +#include "eclipseOS.h" +#include "eclipseGtk.h" + +#include <locale.h> +#include <dlfcn.h> +#include <stdio.h> + +#define ECLIPSE_ICON 401 + +char dirSeparator = '/'; +char pathSeparator = ':'; + +/* Define local variables for the main window. */ +static int saveArgc = 0; /* arguments after they were parsed, for window system */ +static char** saveArgv = 0; + +gboolean gtkInitialized = FALSE; + +#ifdef SOLARIS +/* a call to this function appears inline in glib/gstring.h on Solaris, + so provide a definition here and hook it up + */ +GString* g_string_insert_c (GString *string, gssize pos, gchar c) { + /* see bug 264615, we can get here without having initialized the gtk pointers */ + if (gtk.not_initialized) + loadGtk(); + return gtk.g_string_insert_c(string, pos, c); +} +#endif + +/* Display a Message */ +void displayMessage(char* title, char* message) +{ + GtkWidget* dialog; + + /* If GTK has not been initialized yet, do it now. */ + if (initWindowSystem( &saveArgc, saveArgv, 1 ) != 0) { + printf("%s:\n%s\n", title, message); + return; + } + + dialog = gtk.gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "%s", message); + gtk.gtk_window_set_title((GtkWindow*)dialog, title); + gtk.gtk_dialog_run((GtkDialog*)dialog); + gtk.gtk_widget_destroy(dialog); +} + +/* Initialize the Window System */ +int initWindowSystem(int* pArgc, char* argv[], int showSplash) +{ + int defaultArgc = 1; + char * defaultArgv [] = { "", 0 }; + + if(gtkInitialized) + return 0; + + /* load the GTK libraries and initialize function pointers */ + if (loadGtk() != 0) + return -1; + + if (getOfficialName() != NULL) + defaultArgv[0] = getOfficialName(); + + if (argv == NULL) { + /* gtk_init_check on Solaris 9 doesn't like NULL or empty argv */ + pArgc = &defaultArgc; + argv = defaultArgv; + } + + /* Save the arguments in case displayMessage() is called in the main launcher. */ + if (saveArgv == 0) + { + saveArgc = *pArgc; + saveArgv = argv; + } + + /* Initialize GTK. */ + if (gtk.gtk_set_locale) gtk.gtk_set_locale(); + if (gtk.gtk_init_with_args) { + GError *error = NULL; + if (!gtk.gtk_init_with_args(pArgc, &argv, NULL, NULL, NULL, &error)) { + if (error) { + fprintf(stderr, "%s: %s\n", getOfficialName(), error->message); + if (gtk.g_error_free) gtk.g_error_free(error); + } + return -1; + } + } else { + if (!gtk.gtk_init_check(pArgc, &argv)) { + return -1; + } + } + + /*_gdk_set_program_class(getOfficialName());*/ + gtkInitialized = TRUE; + return 0; +} + +/* Load the specified shared library + */ +void * loadLibrary( char * library ){ + void * result= dlopen(library, RTLD_LAZY); + if(result == 0) + printf("%s\n",dlerror()); + return result; +} + +/* Unload the shared library + */ +void unloadLibrary( void * handle ){ + dlclose(handle); +} + +/* Find the given symbol in the shared library + */ +void * findSymbol( void * handle, char * symbol ){ + return dlsym(handle, symbol); +} + diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkInit.c b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkInit.c new file mode 100644 index 000000000..51ed70a9f --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/eclipseGtkInit.c @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include "eclipseGtk.h" +#include "eclipseCommon.h" +#include <dlfcn.h> +#include <string.h> +#include <stdlib.h> + +struct GTK_PTRS gtk = { 1 }; /* initialize the first field "not_initialized" so we can tell when we've loaded the pointers */ + +/* tables to help initialize the function pointers */ +/* functions from libgtk-x11-2.0 or libgtk-3.so.0*/ +static FN_TABLE gtkFunctions[] = { + FN_TABLE_ENTRY(gtk_container_add, 1), + FN_TABLE_ENTRY(gtk_dialog_run, 1), + FN_TABLE_ENTRY(gtk_image_new_from_pixbuf, 1), + FN_TABLE_ENTRY(gtk_init_check, 1), + FN_TABLE_ENTRY(gtk_init_with_args, 0), + FN_TABLE_ENTRY(gtk_message_dialog_new, 1), + FN_TABLE_ENTRY(gtk_set_locale, 0), + FN_TABLE_ENTRY(gtk_widget_destroy, 1), + FN_TABLE_ENTRY(gtk_widget_destroyed, 1), + FN_TABLE_ENTRY(gtk_widget_show_all, 1), + FN_TABLE_ENTRY(gtk_window_new, 1), + FN_TABLE_ENTRY(gtk_window_resize, 1), + FN_TABLE_ENTRY(gtk_window_set_title, 1), + FN_TABLE_ENTRY(gtk_window_set_decorated, 1), + FN_TABLE_ENTRY(gtk_window_set_position, 1), + { NULL, NULL } +}; +/* functions from libgdk-x11-2.0 or libgdk-3.so.0*/ +static FN_TABLE gdkFunctions[] = { + FN_TABLE_ENTRY(gdk_set_program_class, 1), + FN_TABLE_ENTRY(gdk_display_get_default, 1), + FN_TABLE_ENTRY(gdk_x11_display_get_xdisplay, 1), + { NULL, NULL } +}; +/* functions from libgdk_pixbuf-2.0 */ +static FN_TABLE pixFunctions[] = { + FN_TABLE_ENTRY(gdk_pixbuf_new_from_file, 1), + FN_TABLE_ENTRY(gdk_pixbuf_get_width, 1), + FN_TABLE_ENTRY(gdk_pixbuf_get_height, 1), + { NULL, NULL } +}; +/* functions from libgobject-2.0 */ +static FN_TABLE gobjFunctions[] = { + FN_TABLE_ENTRY(g_signal_connect_data, 1), + FN_TABLE_ENTRY(g_main_context_iteration, 1), + FN_TABLE_ENTRY(g_object_unref, 1), + FN_TABLE_ENTRY(g_timeout_add, 1), + FN_TABLE_ENTRY(g_error_free, 1), +#ifdef SOLARIS + FN_TABLE_ENTRY(g_string_insert_c, 1), +#endif + { NULL, NULL } +}; + +/* functions from libX11 */ +static FN_TABLE x11Functions[] = { + FN_TABLE_ENTRY(XGetSelectionOwner, 1), + FN_TABLE_ENTRY(XSetSelectionOwner, 1), + FN_TABLE_ENTRY(XCreateWindow, 1), + FN_TABLE_ENTRY(XChangeProperty, 1), + FN_TABLE_ENTRY(XSync, 1), + FN_TABLE_ENTRY(XRootWindow, 1), + FN_TABLE_ENTRY(XDefaultScreen, 1), + FN_TABLE_ENTRY(XInternAtom, 1), + { NULL, NULL } +}; + + +static int loadGtkSymbols( void * library, FN_TABLE * table) { + int i = 0; + void * fn; + for (i = 0; table[i].fnName != NULL; i++) { + fn = findSymbol(library, table[i].fnName); + if (fn != 0) { + *(table[i].fnPtr) = fn; + } else { + if (table[i].required) return -1; + } + } + return 0; +} + +int loadGtk() { +#ifdef AIX +#define DLFLAGS RTLD_LAZY | RTLD_MEMBER +#else +#define DLFLAGS RTLD_LAZY +#endif + + void *gdkLib = NULL, *gtkLib = NULL, *objLib = NULL, *pixLib = NULL, *x11Lib = NULL; + + if (getenv("SWT_GTK3")) { + gdkLib = dlopen(GDK3_LIB, DLFLAGS); + gtkLib = dlopen(GTK3_LIB, DLFLAGS); + } + if (!gtkLib || !gdkLib) { + gdkLib = dlopen(GDK_LIB, DLFLAGS); + gtkLib = dlopen(GTK_LIB, DLFLAGS); + } + objLib = dlopen(GOBJ_LIB, DLFLAGS); + pixLib = dlopen(PIXBUF_LIB, DLFLAGS); + x11Lib = dlopen(X11_LIB, DLFLAGS); + + /* initialize ptr struct to 0's */ + memset(>k, 0, sizeof(struct GTK_PTRS)); + + if ( gtkLib == NULL || loadGtkSymbols(gtkLib, gtkFunctions) != 0) return -1; + if ( gdkLib == NULL || loadGtkSymbols(gdkLib, gdkFunctions) != 0) return -1; + if ( pixLib == NULL || loadGtkSymbols(pixLib, pixFunctions) != 0) return -1; + if ( objLib == NULL || loadGtkSymbols(objLib, gobjFunctions) != 0) return -1; + if ( x11Lib == NULL || loadGtkSymbols(x11Lib, x11Functions) != 0) return -1; + + return 0; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/make_aix.mak b/features/org.eclipse.equinox.executable.feature/library/gtk/make_aix.mak new file mode 100644 index 000000000..2d3a71d9b --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/make_aix.mak @@ -0,0 +1,116 @@ +#******************************************************************************* +# Copyright (c) 2010, 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Tom Tromey (Red Hat, Inc.) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the GTK eclipse launcher program. +# +# This makefile expects the utility "pkg-config" to be in the PATH. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - JAVA_HOME for jni headers +#default value for PROGRAM_OUTPUT + +PROGRAM_OUTPUT=eclipse +PROGRAM_LIBRARY=$(PROGRAM_OUTPUT)_$(LIB_VERSION).so + + +# Define the object modules to be compiled and flags. +CC=gcc +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseGtkCommon.o eclipseGtkInit.o +DLL_OBJS = eclipse.o eclipseGtk.o eclipseUtil.o eclipseJNI.o eclipseMozilla.o eclipseShm.o eclipseNix.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lpthread -ldl -lX11 +LIBS = -lpthread -ldl + +X11_LIB_ppc = shr4.o +X11_LIB_ppc64 = shr_64.o +X11_LIB = -DX11_LIB="\"libX11.a($(X11_LIB_$(DEFAULT_OS_ARCH)))\"" +GTK_LIBS = -DGTK_LIB="\"libgtk-x11-2.0.a(libgtk-x11-2.0.so.0)\"" \ + -DGDK_LIB="\"libgdk-x11-2.0.a(libgdk-x11-2.0.so.0)\"" \ + -DGTK3_LIB="\"libgtk-3.a(libgtk-3.so.0)\"" \ + -DGDK3_LIB="\"libgdk-3.a(libgdk-3.so.0)\"" \ + -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.a(libgdk_pixbuf-2.0.so.0)\"" \ + -DGOBJ_LIB="\"libgobject-2.0.a(libgobject-2.0.so.0)\"" \ + $(X11_LIB) + +LFLAGS = ${M_ARCH} -shared +CFLAGS = ${M_ARCH} -g -s -Wall\ + -fpic \ + -DAIX \ + -DMOZILLA_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -D$(DEFAULT_JAVA) \ + $(GTK_LIBS) \ + -I. \ + -I.. \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \ + `pkg-config --cflags gtk+-2.0` + +all: $(EXEC) $(DLL) + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o eclipse.o + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(CC) $(CFLAGS) -c ../eclipseMain.c -o eclipseMain.o + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(CFLAGS) -c ../eclipseCommon.c + +eclipseGtkCommon.o: ../eclipseCommon.h ../eclipseOS.h eclipseGtk.h eclipseGtkCommon.c + $(CC) $(CFLAGS) -c eclipseGtkCommon.c -o eclipseGtkCommon.o + +eclipseGtkInit.o: ../eclipseCommon.h eclipseGtk.h eclipseGtkInit.c + $(CC) $(CFLAGS) -c eclipseGtkInit.c -o eclipseGtkInit.o + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o eclipseUtil.o + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o eclipseJNI.o + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o eclipseConfig.o + +eclipseMozilla.o: ../eclipseMozilla.c ../eclipseMozilla.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseMozilla.c -o eclipseMozilla.o + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o eclipseShm.o + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o eclipseNix.o + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) ${M_ARCH} -Wl,-bM:UR -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + sedmgr -c exempt $(EXEC) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/make_hpux.mak b/features/org.eclipse.equinox.executable.feature/library/gtk/make_hpux.mak new file mode 100644 index 000000000..d0227efc2 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/make_hpux.mak @@ -0,0 +1,102 @@ +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Sumit Sarkar (Hewlett-Packard) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the HPUX/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files + +#ifeq ($(PROGRAM_OUTPUT),) +# PROGRAM_OUTPUT=eclipse +#endif + +DEFAULT_JAVA=DEFAULT_JAVA_EXEC +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +CC=gcc +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseGtkCommon.o eclipseGtkInit.o +DLL_OBJS = eclipse.o eclipseGtk.o eclipseUtil.o eclipseJNI.o eclipseShm.o eclipseNix.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -L$(MOTIF_HOME)/lib -L$(X11_HOME)/lib -lpthread -lrt +GTK_LIBS = \ + -DGTK_LIB="\"libgtk-x11-2.0.so\"" -DGDK_LIB="\"libgdk-x11-2.0.so\"" \ + -DGTK3_LIB="\"libgtk-3.so\"" -DGDK3_LIB="\"libgdk-3.so\"" \ + -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so\"" \ + -DGOBJ_LIB="\"libgobject-2.0.so\"" -DX11_LIB="\"libX11.so\"" +LFLAGS = ${M_ARCH} -shared -static-libgcc +# -Wl,--export-dynamic +CFLAGS = ${M_ARCH} -O -s \ + -DNETSCAPE_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -D$(DEFAULT_JAVA) \ + -DHPUX \ + $(GTK_LIBS) \ + -I./ \ + -I../ \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/hp-ux \ + `pkg-config --cflags gtk+-2.0` + +all: $(EXEC) $(DLL) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c ../eclipseMain.c -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) ${M_ARCH} -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak b/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak new file mode 100644 index 000000000..6abe01702 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak @@ -0,0 +1,112 @@ +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Tom Tromey (Red Hat, Inc.) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the GTK eclipse launcher program. +# +# This makefile expects the utility "pkg-config" to be in the PATH. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - JAVA_HOME for jni headers +#default value for PROGRAM_OUTPUT +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +endif + +PROGRAM_LIBRARY=$(PROGRAM_OUTPUT)_$(LIB_VERSION).so + +ifeq ($(DEFAULT_JAVA),) + DEFAULT_JAVA=DEFAULT_JAVA_JNI +endif + +# Define the object modules to be compiled and flags. +CC?=gcc +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseGtkCommon.o eclipseGtkInit.o +DLL_OBJS = eclipse.o eclipseGtk.o eclipseUtil.o eclipseJNI.o eclipseMozilla.o eclipseShm.o eclipseNix.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lpthread -ldl -lX11 +LIBS = -lpthread -ldl +GTK_LIBS = \ + -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" \ + -DGTK3_LIB="\"libgtk-3.so.0\"" -DGDK3_LIB="\"libgdk-3.so.0\"" \ + -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\"" -DX11_LIB="\"libX11.so.6\"" +LFLAGS = ${M_ARCH} -shared -fpic -Wl,--export-dynamic +CFLAGS = ${M_ARCH} -g -s -Wall\ + -fpic \ + -DLINUX \ + -DMOZILLA_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -D$(DEFAULT_JAVA) \ + $(GTK_LIBS) \ + -I. \ + -I.. \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \ + `pkg-config --cflags gtk+-2.0` + +all: $(EXEC) $(DLL) + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o eclipse.o + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(CC) $(CFLAGS) -c ../eclipseMain.c -o eclipseMain.o + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(CFLAGS) -c ../eclipseCommon.c + +eclipseGtkCommon.o: ../eclipseCommon.h ../eclipseOS.h eclipseGtk.h eclipseGtkCommon.c + $(CC) $(CFLAGS) -c eclipseGtkCommon.c -o eclipseGtkCommon.o + +eclipseGtkInit.o: ../eclipseCommon.h eclipseGtk.h eclipseGtkInit.c + $(CC) $(CFLAGS) -c eclipseGtkInit.c -o eclipseGtkInit.o + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o eclipseUtil.o + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o eclipseJNI.o + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o eclipseConfig.o + +eclipseMozilla.o: ../eclipseMozilla.c ../eclipseMozilla.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseMozilla.c -o eclipseMozilla.o + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o eclipseShm.o + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o eclipseNix.o + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) ${M_ARCH} -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/make_solaris.mak b/features/org.eclipse.equinox.executable.feature/library/gtk/make_solaris.mak new file mode 100644 index 000000000..945becf9e --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/make_solaris.mak @@ -0,0 +1,111 @@ +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Tom Tromey (Red Hat, Inc.) +# Martin Oberhuber (Wind River) - [176805] Support building with gcc and debug +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the GTK eclipse launcher program. +# +# This makefile expects the utility "pkg-config" to be in the PATH. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - JAVA_HOME for JNI headers + +#ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +#endif + +PROGRAM_LIBRARY=$(PROGRAM_OUTPUT)_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseGtkCommon.o eclipseGtkInit.o +DLL_OBJS = eclipse.o eclipseGtk.o eclipseUtil.o eclipseJNI.o eclipseMozilla.o eclipseShm.o eclipseNix.o +PICFLAG = -K PIC +# Optimize and remove all debugging information by default +OPTFLAG = -O -s +# OPTFLAG = -g + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +#LIBS = `pkg-config --libs-only-L gtk+-2.0` -lgtk-x11-2.0 -lgdk_pixbuf-2.0 -lgobject-2.0 -lgdk-x11-2.0 -lglib-2.0 -lthread -ldl -lc +LIBS = -lthread -ldl -lc -lrt +GTK_LIBS = \ + -DGTK_LIB="\"libgtk-x11-2.0.so.0\"" -DGDK_LIB="\"libgdk-x11-2.0.so.0\"" \ + -DGTK3_LIB="\"libgtk-3.so.0\"" -DGDK3_LIB="\"libgdk-3.so.0\"" \ + -DPIXBUF_LIB="\"libgdk_pixbuf-2.0.so.0\"" -DGOBJ_LIB="\"libgobject-2.0.so.0\"" -DX11_LIB="\"libX11.so.4\"" +LFLAGS = -G +CFLAGS = $(OPTFLAG) \ + -DSOLARIS \ + $(PICFLAG) \ + -DMOZILLA_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + $(GTK_LIBS) \ + -I. \ + -I.. \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/solaris \ + `pkg-config --cflags gtk+-2.0` + +all: $(EXEC) $(DLL) + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o eclipse.o + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(CC) $(CFLAGS) -c ../eclipseMain.c -o eclipseMain.o + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(CFLAGS) -c ../eclipseCommon.c + +eclipseGtkCommon.o: ../eclipseCommon.h ../eclipseOS.h eclipseGtk.h eclipseGtkCommon.c + $(CC) $(CFLAGS) -c eclipseGtkCommon.c -o eclipseGtkCommon.o + +eclipseGtkInit.o: ../eclipseCommon.h eclipseGtk.h eclipseGtkInit.c + $(CC) $(CFLAGS) -c eclipseGtkInit.c -o eclipseGtkInit.o + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o eclipseUtil.o + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o eclipseJNI.o + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o eclipseConfig.o + +eclipseMozilla.o: ../eclipseMozilla.c ../eclipseMozilla.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseMozilla.c -o eclipseMozilla.o + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o eclipseShm.o + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o eclipseNix.o + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/make_version.mak b/features/org.eclipse.equinox.executable.feature/library/make_version.mak new file mode 100644 index 000000000..41c9b799c --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/make_version.mak @@ -0,0 +1,14 @@ +#******************************************************************************* +# Copyright (c) 2006, 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +#******************************************************************************* + +maj_ver=1 +min_ver=505 +LIB_VERSION = $(maj_ver)$(min_ver) diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/.cvsignore b/features/org.eclipse.equinox.executable.feature/library/motif/.cvsignore new file mode 100644 index 000000000..e64b3dbf5 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/.cvsignore @@ -0,0 +1,4 @@ +*.o +eclipse +eclipse_*.so +libeclipse-motif.so diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.c b/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.c new file mode 100644 index 000000000..2f4e525b0 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.c @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include "NgCommon.h" + +/* Non-zero = big-endian architecture */ +static BYTE4 hostIsMSB = 0; + +/* Store last error msg */ +#define MAX_MSG_SIZE 100 +char errorMsg[MAX_MSG_SIZE]; + +/* Library initialization */ +void NgInit() +{ + BYTE4 result = (BYTE4) 'A'; + + /* determine the byte ordering of the host machine */ + hostIsMSB = (BYTE4) (*((char *) &result) != 'A'); + + errorMsg[0] = 0; +} + +/** + * Memory allocation routine + */ +void *NgMalloc (UBYTE4 size) +{ + return malloc (size); +} + +/** + * Memory allocation routine + */ +void NgFree (void *memblock) +{ + if (memblock != NULL) + free (memblock); +} + +void NgMemSet (void *dest, UBYTE1 c, BYTE4 count) +{ + memset (dest, c, count); +} + +void NgMemCpy (void *dest, void *src, BYTE4 count) +{ + memcpy (dest, src, count); +} + +/** + * Error Reporting + */ + +ng_err_t NgError (ng_err_t error_type, char* msg) { + if (msg != NULL) + { + /* Store a copy of the last error msg - truncate if necessary */ + size_t size = strlen (msg); + if (size >= MAX_MSG_SIZE) size = MAX_MSG_SIZE - 1; + NgMemCpy (errorMsg, msg, size); + errorMsg[size] = 0; + } + return error_type; +} + +const char *NgGetLastErrorMsg() +{ + return errorMsg; +} + +/** + * Stream manipulation routines + */ +ng_err_t NgStreamInit (ng_stream_t *stream, char *fullname) +{ + stream->file = fopen (fullname, "rb"); + stream->size = 0; + stream->pos = 0; + if (stream->file == NULL) return NgError (ERR_NG, "Can't open file"); + return ERR_OK; +} + +void NgStreamClose (ng_stream_t *stream) +{ + if (stream->file != NULL) + { + fclose (stream->file); + stream->file = NULL; + } + stream->size = -1; +} + +char NgStreamEof (ng_stream_t *stream) +{ + return stream->size == -1; +} + +BYTE4 NgStreamGetPosition (ng_stream_t *stream) +{ + return stream->pos; +} + +BYTE4 NgStreamSkip (ng_stream_t *stream, BYTE4 nbr) +{ + if (stream->size == -1) return 0; + if (fseek (stream->file, nbr, SEEK_CUR)) + { + NgStreamClose (stream); + return 0; + } + stream->pos += nbr; + return nbr; +} + +BYTE4 NgStreamRead (ng_stream_t *stream, char *buffer, BYTE4 nbr) +{ + size_t cnt; + if (stream->size == -1) return 0; + cnt = fread (buffer, sizeof (char), nbr, stream->file); + if (cnt != nbr) + { + NgStreamClose (stream); + return 0; + } + stream->pos += nbr; + return nbr; +} + +BYTE1 NgIsMSB() +{ + return hostIsMSB != 0; +} + +UBYTE2 SystemToLittleEndianUBYTE2 (UBYTE2 value) +{ + return hostIsMSB ? ((value&0xFF) << 8)|((value&0xFF00)>>8) : value; +} + +UBYTE4 SystemToLittleEndianUBYTE4 (UBYTE4 value) +{ + return hostIsMSB ? ((value&0xFF000000L)>>24)|((value&0xFF0000L)>>8) | ((value&0xFF00L)<<8) | ((value&0xFFL)<<24) : value; +} + +UBYTE2 SystemToBigEndianUBYTE2 (UBYTE2 value) +{ + return hostIsMSB ? value : ((value&0xFF) << 8)|((value&0xFF00)>>8); +} + +UBYTE2 LittleEndianToSystemUBYTE2 (UBYTE2 value) +{ + return hostIsMSB ? ((value&0xFF) << 8)|((value&0xFF00)>>8) : value; +} + +UBYTE4 LittleEndianToSystemUBYTE4 (UBYTE4 value) +{ + return hostIsMSB ? ((value&0xFF000000L)>>24)|((value&0xFF0000L)>>8) | ((value&0xFF00L)<<8) | ((value&0xFFL)<<24) : value; +} + +UBYTE2 BigEndianToSystemUBYTE2 (UBYTE2 value) +{ + return hostIsMSB ? value : ((value&0xFF) << 8)|((value&0xFF00)>>8); +} + +UBYTE4 BigEndianToSystemUBYTE4 (UBYTE4 value) +{ + return hostIsMSB ? value : ((value&0xFF000000L)>>24)|((value&0xFF0000L)>>8)|((value&0xFF00L)<<8) | ((value&0xFFL)<<24); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.h b/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.h new file mode 100644 index 000000000..31252d753 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgCommon.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef __NG_COMMON_H +#define __NG_COMMON_H + +#include <memory.h> +#include <stdio.h> + +typedef char BYTE1; +typedef unsigned char UBYTE1; +typedef short BYTE2; +typedef unsigned short UBYTE2; +typedef long BYTE4; +typedef unsigned long UBYTE4; + +/* error reporting */ +#define ERR_OK 1 +#define ERR_SUBSCRIPT_OUT_OF_RANGE -1 +#define ERR_INVALID_BIT_COUNT -2 +#define ERR_NG -4 + +typedef BYTE4 ng_err_t; +ng_err_t NgError (ng_err_t error_type, char* msg); +const char *NgGetLastErrorMsg(); + +/** + * NgInit + * Must be called prior to using the image decoders + */ +void NgInit(); + +/* memory management */ +void *NgMalloc (UBYTE4 size); +void NgFree (void *memblock); +void NgMemSet (void *dest, UBYTE1 c, BYTE4 count); +void NgMemCpy (void *dest, void *src, BYTE4 count); + +/* stream api */ +typedef struct { + FILE *file; + BYTE4 size; + BYTE4 pos; +} ng_stream_t; + +/** + * Init a stream given the path and name of a file + * Note. NgStreamClose should be called to release + * the related OS resource. + */ +ng_err_t NgStreamInit (ng_stream_t *stream, char *fullname); + +/** + * Close any OS resource managed the given stream. + * In particular, close the file if the stream is using one. + */ +void NgStreamClose (ng_stream_t *stream); + +char NgStreamEof (ng_stream_t *stream); + +BYTE4 NgStreamGetPosition (ng_stream_t *stream); +/** + * Skips nbr bytes. + * Return nbr if all bytes were skipped. + * If nbr bytes can't be skipped, the stream is closed + * (NgStreamEof returns 1). 0 is returned. + */ +BYTE4 NgStreamSkip (ng_stream_t *stream, BYTE4 nbr); +/** + * Copies nbr bytes to buffer from stream. + * Returns nbr if all bytes were copied. + * If nbr bytes can't be read, no bytes are copied. The stream + * is closed (NgStreamEof returns 1). 0 is returned. + */ +BYTE4 NgStreamRead (ng_stream_t *stream, char *buffer, BYTE4 nbr); + +/* little/big endian conversion */ +BYTE1 NgIsMSB(); +UBYTE2 SystemToLittleEndianUBYTE2 (UBYTE2); +UBYTE4 SystemToLittleEndianUBYTE4 (UBYTE4); +UBYTE2 SystemToBigEndianUBYTE2 (UBYTE2); +UBYTE2 LittleEndianToSystemUBYTE2 (UBYTE2); +UBYTE4 LittleEndianToSystemUBYTE4 (UBYTE4); +UBYTE2 BigEndianToSystemUBYTE2 (UBYTE2); +UBYTE4 BigEndianToSystemUBYTE4 (UBYTE4); + +#endif /* NG_COMMON_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.c b/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.c new file mode 100644 index 000000000..056b09de3 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.c @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include "NgCommon.h" +#include "NgImageData.h" +#include "NgImage.h" +#include "NgWinBMPFileFormat.h" +#include <dlfcn.h> + +struct NG_PTRS ng; + +#define FN_TABLE_ENTRY(fn) { (void**)&ng.fn, #fn } +typedef struct { + void ** fnPtr; + char * fnName; +} FN_TABLE; +static FN_TABLE x11Functions[] = { FN_TABLE_ENTRY(XCreateGC), + FN_TABLE_ENTRY(XCreateImage), + FN_TABLE_ENTRY(XCreatePixmap), + FN_TABLE_ENTRY(XDefaultColormap), + FN_TABLE_ENTRY(XDefaultDepthOfScreen), + FN_TABLE_ENTRY(XDefaultRootWindow), + FN_TABLE_ENTRY(XDefaultScreen), + FN_TABLE_ENTRY(XDefaultScreenOfDisplay), + FN_TABLE_ENTRY(XDefaultVisual), + FN_TABLE_ENTRY(XFreeGC), + FN_TABLE_ENTRY(XFreePixmap), + FN_TABLE_ENTRY(XPutImage), + FN_TABLE_ENTRY(XQueryColor), + { NULL, NULL } + }; + +static FN_TABLE xtFunctions[] = { FN_TABLE_ENTRY(XtMalloc), {NULL, NULL} }; + +int NGImageInit() { + int i = 0; + void * fn; +#ifdef AIX + void * x11Lib = dlopen(X11_LIB, RTLD_LAZY | RTLD_MEMBER); + void * xtLib = dlopen(XT_LIB, RTLD_LAZY | RTLD_MEMBER); +#else + void * x11Lib = dlopen(X11_LIB, RTLD_LAZY); + void * xtLib = dlopen(XT_LIB, RTLD_LAZY); +#endif + /* initialize ptr struct to 0's */ + memset(&ng, 0, sizeof(struct NG_PTRS)); + + + if (x11Lib == NULL || xtLib == NULL) + return -1; + + for (i = 0; x11Functions[i].fnName != NULL; i++) { + fn = dlsym(x11Lib, x11Functions[i].fnName); + if (fn != 0) + *(x11Functions[i].fnPtr) = fn; + else + return -1; + } + + for (i = 0; xtFunctions[i].fnName != NULL; i++) { + fn = dlsym(xtLib, xtFunctions[i].fnName); + if (fn != 0) + *(xtFunctions[i].fnPtr) = fn; + else + return -1; + } + return 0; +} +/** + * Return the nbr of entries in the default color palette + */ +int getNbrColorsXPalette(Display *xDisplay) +{ + Visual *visual = ng.XDefaultVisual (xDisplay, ng.XDefaultScreen(xDisplay)); + return visual->map_entries; +} + +/** + * Return the RGB codes of the default palette + * palette: buffer of size numColors * 3, holding the RGB values + */ +ng_err_t getXPalette (Display *xDisplay, int numColors, char* palette) +{ + XColor color; + int i; + int index = 0; + int colormap = ng.XDefaultColormap (xDisplay, ng.XDefaultScreen(xDisplay)); + for (i = 0; i < numColors; i++) + { + color.pixel = i; + ng.XQueryColor (xDisplay, colormap, &color); + palette[index++] = ((color.red >> 8) & 0xFF); + palette[index++] = ((color.green >> 8) & 0xFF); + palette[index++] = ((color.blue >> 8) & 0xFF); + } + return ERR_OK; +} + +/** + * Put a device-independent image of any depth into a drawable of the same size, + */ +ng_err_t putImage(ng_bitmap_image_t *image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, + Display *xDisplay, Visual *visual, int screenDepth, + int drawable) +{ + + XImage *xImagePtr; + int bufSize; + int destRedMask = 0, destGreenMask = 0, destBlueMask = 0; + BYTE1 screenDirect; + UBYTE1 *srcData = NgBitmapImageImageData(image); + UBYTE4 srcDepth = NgBitmapImageBitCount(image); + BYTE4 sbpp, dbpp; + GC tempGC; + int numColors = 0; + + /* We only support image depth of 24 bits */ + if (srcDepth != 24) return NgError (ERR_NG, "Error unsupported depth - only support 24 bit"); + if (screenDepth <= 8) + { + numColors = getNbrColorsXPalette (xDisplay); + if (numColors == 0) + return NgError (ERR_NG, "Error pseudo-color mode detected, no colors available"); + numColors = 1 << ng.XDefaultDepthOfScreen (ng.XDefaultScreenOfDisplay (xDisplay)); + screenDirect = 0; + } else + { + destRedMask = visual->red_mask; + destGreenMask = visual->green_mask; + destBlueMask = visual->blue_mask; + screenDirect = 1; + } + + xImagePtr = ng.XCreateImage(xDisplay, visual, screenDepth, ZPixmap, 0, 0, srcWidth, srcHeight, 32, 0); + if (xImagePtr == NULL) return NgError (ERR_NG, "Error XCreateImage failed"); + bufSize = xImagePtr->bytes_per_line * srcHeight; + + xImagePtr->data = (char*) ng.XtMalloc (bufSize); + sbpp = NgBitmapImageBytesPerRow(image); + dbpp = xImagePtr->bytes_per_line; + + if (screenDirect) + { + /* 24 bit source to direct screen destination */ + NgBitmapImageBlitDirectToDirect(srcData, sbpp, srcWidth, srcHeight, + (UBYTE1*)xImagePtr->data, xImagePtr->bits_per_pixel, dbpp, xImagePtr->byte_order, + destRedMask, destGreenMask, destBlueMask); + } else + { + /* 24 bit source to palette screen destination */ + char *palette = (char*) NgMalloc (numColors * 3); + getXPalette (xDisplay, numColors, palette); + NgBitmapImageBlitDirectToPalette(srcData, sbpp, srcWidth, srcHeight, + (UBYTE1*)xImagePtr->data, xImagePtr->bits_per_pixel, dbpp, xImagePtr->byte_order, + (UBYTE1*)palette, numColors); + NgFree (palette); + } + + tempGC = ng.XCreateGC (xDisplay, drawable, 0, NULL); + ng.XPutImage(xDisplay, drawable, tempGC, xImagePtr, 0, 0, 0, 0, srcWidth, srcHeight); + + XDestroyImage (xImagePtr); + ng.XFreeGC (xDisplay, tempGC); + return ERR_OK; +} + +ng_err_t init(ng_bitmap_image_t *image, Display *xDisplay, int screenDepth, int drawable, Pixmap *pixmap) +{ + ng_err_t err; + int width = (int)NgBitmapImageWidth(image); + int height = (int)NgBitmapImageHeight(image); + + Visual *visual = ng.XDefaultVisual(xDisplay, ng.XDefaultScreen(xDisplay)); + *pixmap = ng.XCreatePixmap(xDisplay, drawable, width, height, screenDepth); + if (*pixmap == 0) + { + return NgError (ERR_NG, "Error XCreatePixmap failed"); + } + err = putImage(image, 0, 0, width, height, 0, 0, xDisplay, visual, screenDepth, *pixmap); + if (err != ERR_OK) + { + ng.XFreePixmap (xDisplay, *pixmap); + return NgError (err, "Error putImage failed"); + } + + return ERR_OK; +} + +/** + * loadBMPImage + * Create a pixmap representing the given BMP file, for the specified display and screen. + * + * display: connection to X server + * screen: the screen to create the pixmap for + * bmpPathname: absolute path and name to the bmp file + * + * returned value: the pixmap newly created if successful. 0 otherwise. + */ +Pixmap loadBMPImage (Display *display, Screen *screen, char *bmpPathname) { + Window drawable; + ng_stream_t in; + ng_bitmap_image_t image; + ng_err_t err = ERR_OK; + int screenDepth; + Pixmap pixmap; + + /* this must be called before any X functions are used */ + NGImageInit(); + NgInit(); + + drawable = ng.XDefaultRootWindow (display); + screenDepth = ng.XDefaultDepthOfScreen (screen); + + if (NgStreamInit (&in, bmpPathname) != ERR_OK) + { + NgError (ERR_NG, "Error can't open BMP file"); + return 0; + } + NgBitmapImageInit (&image); + err = NgBmpDecoderReadImage (&in, &image); + NgStreamClose (&in); + + if (err != ERR_OK) + { + NgBitmapImageFree (&image); + return 0; + } + + err = init (&image, display, screenDepth, drawable, &pixmap); + NgBitmapImageFree (&image); + + return err == ERR_OK ? pixmap : 0; +} + +const char *getBMPErrorMessage () +{ + return NgGetLastErrorMsg (); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.h b/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.h new file mode 100644 index 000000000..a12218fb2 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgImage.h @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef __NG_IMAGE_H +#define __NG_IMAGE_H + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> +#include <X11/Intrinsic.h> + +struct NG_PTRS { + GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*); + XImage * (*XCreateImage) (Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); + Pixmap (*XCreatePixmap) (Display*, Drawable, unsigned int, unsigned int, unsigned int); + Colormap (*XDefaultColormap) (Display*, int); + int (*XDefaultDepthOfScreen)(Screen*); + Window (*XDefaultRootWindow) (Display*); + int (*XDefaultScreen) (Display*); + Screen * (*XDefaultScreenOfDisplay)(Display*); + Visual * (*XDefaultVisual) (Display*, int); + int (*XFreeGC) (Display*, GC); + int (*XFreePixmap) (Display*, Pixmap); + int (*XPutImage) (Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int); + int (*XQueryColor) (Display*, Colormap, XColor*); + char * (*XtMalloc) (Cardinal); +}; + +/** + * loadBMPImage + * Create a pixmap representing the given BMP file, for the specified display and screen. + * + * display: connection to X server + * screen: the screen to create the pixmap for + * bmpPathname: absolute path and name to the bmp file + * + * returned value: the pixmap newly created if successful. 0 otherwise. + */ +Pixmap loadBMPImage (Display *display, Screen *screen, char *bmpPathname); + +/** + * Return error message describing why the BMP file could not be displayed + */ +const char *getBMPErrorMessage(); + +#endif /* NG_IMAGE_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.c b/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.c new file mode 100644 index 000000000..96053b305 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.c @@ -0,0 +1,490 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include "NgImageData.h" + +static UBYTE4 RoundRow (UBYTE4 width) +{ + UBYTE4 result = (width + RowRounding - 1) + & ~(RowRounding - 1) ; + return result ; +} + +void NgBitmapImageInit (ng_bitmap_image_t *image) +{ + NgBitmapImageClearData (image); +} + +void NgBitmapImageFree (ng_bitmap_image_t *image) +{ + NgFree (image->color_map); + NgFree (image->image_data); + NgFree (image->alpha_data); +} + +void NgBitmapImageClearData (ng_bitmap_image_t *image) +{ + image->bit_count = 0; + image->image_width = 0; + image->image_height = 0; + image->color_count = 0; + image->color_map = NULL; + image->image_data = NULL; + image->alpha_data = NULL; + image->transparent_pixel = -1; +} + +void NgBitmapImageSetSize(ng_bitmap_image_t *image, + UBYTE4 color_count, + UBYTE4 bits, + UBYTE4 width, + UBYTE4 height) +{ + NgFree (image->color_map); + NgFree (image->image_data); + NgBitmapImageClearData (image); + + switch (bits) + { + case 1: + case 2: + case 4: + case 8: + { + UBYTE4 bitsize; + UBYTE4 bytecount; + + image->bit_count = bits; + image->color_count = color_count; + image->image_width = width; + image->image_height = height; + + image->color_map = (ng_color_map_entry_t *) NgMalloc (sizeof(ng_color_map_entry_t) * image->color_count); + NgMemSet (image->color_map, 0, sizeof (ng_color_map_entry_t) * image->color_count); + bitsize = image->bit_count * image->image_width; + image->row_width = RoundRow ((bitsize + 7)/8); + bytecount = image->row_width * image->image_height; + image->image_data = (UBYTE1 *) NgMalloc (bytecount); + NgMemSet (image->image_data, 0, (BYTE4)bytecount); + } + break ; + case 16: + { + image->bit_count = bits; + image->color_count = color_count; + image->image_width = width; + image->image_height = height; + image->row_width = RoundRow (2 * image->image_width); + image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height); + NgMemSet (image->image_data, 0, image->row_width * image->image_height); + } + break; + case 24: + { + image->bit_count = bits; + image->color_count = color_count; + image->image_width = width; + image->image_height = height; + image->row_width = RoundRow (3 * image->image_width); + image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height); + NgMemSet (image->image_data, 0, image->row_width * image->image_height); + } + break; + case 32: + { + image->bit_count = bits; + image->color_count = color_count; + image->image_width = width; + image->image_height = height; + image->row_width = RoundRow (4 * image->image_width); + image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height); + NgMemSet (image->image_data, 0, image->row_width * image->image_height); + } + break ; + default: + NgError (ERR_INVALID_BIT_COUNT, NULL); + } +} + +ng_color_map_entry_t *NgBitmapImageColorMap (ng_bitmap_image_t *image, UBYTE4 index) +{ + if (index >= image->color_count) + { + NgError (ERR_SUBSCRIPT_OUT_OF_RANGE, "Error NgBitmapImageColorMap failed"); + return NULL; + } + + return &image->color_map [index] ; +} + +/* blit constants */ +#define TYPE_INDEX_1_MSB 1 +#define TYPE_INDEX_1_LSB 2 +#define TYPE_INDEX_2 3 +#define TYPE_INDEX_4 4 +#define TYPE_INDEX_8 5 +#define TYPE_GENERIC_24 6 +#define TYPE_GENERIC_8 7 +#define TYPE_GENERIC_16_MSB 8 +#define TYPE_GENERIC_16_LSB 9 +#define TYPE_GENERIC_32_MSB 10 +#define TYPE_GENERIC_32_LSB 11 + +/** + * Computes the required channel shift from a mask. + */ +UBYTE4 getChannelShift(UBYTE4 mask) +{ + UBYTE4 i; + if (mask == 0) return 0; + for (i = 0; ((mask & 1) == 0) && (i < 32); ++i) + { + mask >>= 1; + } + return i; +} + +/** + * Computes the required channel width (depth) from a mask. + */ +UBYTE4 getChannelWidth(UBYTE4 mask, UBYTE4 shift) +{ + UBYTE4 i; + if (mask == 0) return 0; + mask >>= shift; + for (i = shift; ((mask & 1) != 0) && (i < 32); ++i) + { + mask >>= 1; + } + return i - shift; +} + +/** + * Blits a direct palette image into a direct palette image. + * + * srcData the source byte array containing image data + * srcStride the source number of bytes per line + * srcWidth the width of the source blit region + * srcHeight the height of the source blit region + * destData the destination byte array containing image data + * destDepth the destination depth: one of 8, 16, 24, 32 + * destStride the destination number of bytes per line + * destOrder the destination byte ordering: 0 for LSB, 1 otherwise + * ignored if destDepth is not 16 or 32 + * destRedMask the destination red channel mask + * destGreenMask the destination green channel mask + * destBlueMask the destination blue channel mask + * + * It is assumed that. + * srcDepth: 24 - BGR ordering (BMP format) + * no alpha + * srcX: 0 + * srcY: 0 + * destX: 0 + * destY: 0 + * destWidth: same as srcWidth + * destHeight: same as srcHeight + */ +void NgBitmapImageBlitDirectToDirect( + UBYTE1 *srcData, BYTE4 srcStride, + BYTE4 srcWidth, BYTE4 srcHeight, + UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder, + UBYTE4 destRedMask, UBYTE4 destGreenMask, UBYTE4 destBlueMask) +{ + BYTE4 srcX = 0, srcY = 0, destX = 0, destY = 0, destWidth = srcWidth, destHeight = srcHeight; + + BYTE4 sbpp, stype, spr, dbpp, dtype, dpr, dprxi, dpryi, dp, sp, dy, dx; + BYTE4 destRedShift, destRedWidth; + BYTE4 destRedPreShift, destGreenShift, destGreenWidth, destGreenPreShift; + BYTE4 destBlueShift, destBlueWidth, destBluePreShift; + UBYTE1 r, g, b; + UBYTE4 data; + + /*** Prepare source-related data ***/ + sbpp = 3; + stype = TYPE_GENERIC_24; + + spr = srcY * srcStride + srcX * sbpp; + + /*** Prepare destination-related data ***/ + switch (destDepth) + { + case 8: + dbpp = 1; + dtype = TYPE_GENERIC_8; + break; + case 16: + dbpp = 2; + dtype = (destOrder != 0) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB; + break; + case 24: + dbpp = 3; + dtype = TYPE_GENERIC_24; + break; + case 32: + dbpp = 4; + dtype = (destOrder != 0) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; + break; + default: + return; + } + + dpr = destY * destStride + destX * dbpp; + dprxi = dbpp; + dpryi = destStride; + + /*** Blit ***/ + dp = dpr; + sp = spr; + + /*** Comprehensive blit (apply transformations) ***/ + destRedShift = getChannelShift(destRedMask); + destRedWidth = getChannelWidth(destRedMask, destRedShift); + destRedPreShift = 8 - destRedWidth; + destGreenShift = getChannelShift(destGreenMask); + destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); + destGreenPreShift = 8 - destGreenWidth; + destBlueShift = getChannelShift(destBlueMask); + destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); + destBluePreShift = 8 - destBlueWidth; + + r = 0; g = 0; b = 0; + for (dy = destHeight; dy > 0; --dy, sp = spr += srcStride, dp = dpr += dpryi) + { + for (dx = destWidth; dx > 0; --dx, dp += dprxi) + { + /*** READ NEXT PIXEL ASSUMING BGR ordering (BMP format) ***/ + b = srcData[sp]; + g = srcData[sp + 1]; + r = srcData[sp + 2]; + sp += 3; + /*** WRITE NEXT PIXEL ***/ + data = + (r >> destRedPreShift << destRedShift) | + (g >> destGreenPreShift << destGreenShift) | + (b >> destBluePreShift << destBlueShift); + switch (dtype) + { + case TYPE_GENERIC_8: + { + destData[dp] = (UBYTE1) data; + } break; + case TYPE_GENERIC_16_MSB: + { + destData[dp] = (UBYTE1) (data >> 8); + destData[dp + 1] = (UBYTE1) (data & 0xff); + } break; + case TYPE_GENERIC_16_LSB: + { + destData[dp] = (UBYTE1) (data & 0xff); + destData[dp + 1] = (UBYTE1) (data >> 8); + } break; + case TYPE_GENERIC_24: + { + destData[dp] = (UBYTE1) (data >> 16); + destData[dp + 1] = (UBYTE1) (data >> 8); + destData[dp + 2] = (UBYTE1) (data & 0xff); + } break; + case TYPE_GENERIC_32_MSB: + { + destData[dp] = (UBYTE1) (data >> 24); + destData[dp + 1] = (UBYTE1) (data >> 16); + destData[dp + 2] = (UBYTE1) (data >> 8); + destData[dp + 3] = (UBYTE1) (data & 0xff); + } break; + case TYPE_GENERIC_32_LSB: + { + destData[dp] = (UBYTE1) (data & 0xff); + destData[dp + 1] = (UBYTE1) (data >> 8); + destData[dp + 2] = (UBYTE1) (data >> 16); + destData[dp + 3] = (UBYTE1) (data >> 24); + } break; + } + } + } +} + +/** + * Create a simple hash table used when converting direct colors to values in a palette + * Each bucket stores the RGB codes and the corresponding palette index. + * The key is made from the RGB values. + * It is used as a cache. New entries colliding with older ones simply + * replace them. + */ +ng_palette_bucket_t *NgRGBIndexCreate () +{ + ng_palette_bucket_t *table = (ng_palette_bucket_t *)NgMalloc (RGBIndexTableSize * sizeof (ng_palette_bucket_t)); + NgMemSet (table, 0, RGBIndexTableSize * sizeof (ng_palette_bucket_t)); + return table; +} + +void NgRGBIndexFree (ng_palette_bucket_t *table) +{ + NgFree (table); +} + +void NgRGBIndexSet (ng_palette_bucket_t *table, UBYTE1 r, UBYTE1 g, UBYTE1 b, UBYTE1 index) +{ + int i = (r * g * b) % RGBIndexTableSize; + table[i].blue = b; + table[i].green = g; + table[i].red = r; + table[i].index = index; + table[i].isSet = 1; +} + +int NgRGBIndexGet (ng_palette_bucket_t *table, UBYTE1 r, UBYTE1 g, UBYTE1 b) +{ + int i = (r * g * b) % RGBIndexTableSize; + if (table[i].isSet && table[i].blue == b && table[i].green == g && table[i].red == r) + return table[i].index; + return -1; +} + +/** + * Blits a direct palette image into an index palette image. + * + * srcData the source byte array containing image data + * srcStride the source number of bytes per line + * srcX the top-left x-coord of the source blit region + * srcY the top-left y-coord of the source blit region + * srcWidth the width of the source blit region + * srcHeight the height of the source blit region + * destData the destination byte array containing image data + * destDepth the destination depth: one of 1, 2, 4, 8 + * destStride the destination number of bytes per line + * destOrder the destination byte ordering: 0 if LSB, 1 otherwise; + * ignored if destDepth is not 1 + * destX the top-left x-coord of the destination blit region + * destY the top-left y-coord of the destination blit region + * destWidth the width of the destination blit region + * destHeight the height of the destination blit region + * destColors the destination palette red green blue component intensities + * destNumColors the number of colors in destColors + * + * It is assumed that. + * srcDepth: 24 - BGR ordering (BMP format) + * no alpha + * srcX: 0 + * srcY: 0 + * destX: 0 + * destY: 0 + * destWidth: same as srcWidth + * destHeight: same as srcHeight + */ + +void NgBitmapImageBlitDirectToPalette( + UBYTE1 *srcData, BYTE4 srcStride, + BYTE4 srcWidth, BYTE4 srcHeight, + UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder, + UBYTE1 *destColors, int destNumColors) +{ + BYTE4 srcX = 0, srcY = 0, destX = 0, destY = 0, destWidth = srcWidth, destHeight = srcHeight; + BYTE4 sbpp, spr, dtype, dpr, dp, sp, destPaletteSize, dy, dx, j, dr, dg, db, distance, minDistance; + + UBYTE1 r = 0, g = 0, b = 0, index = 0; + int storedIndex; + ng_palette_bucket_t *RGBIndexTable; + + /*** Prepare source-related data ***/ + sbpp = 3; + spr = srcY * srcStride + srcX * sbpp; + + /*** Prepare destination-related data ***/ + switch (destDepth) + { + case 8: + dtype = TYPE_INDEX_8; + break; + case 4: + destStride <<= 1; + dtype = TYPE_INDEX_4; + break; + case 2: + destStride <<= 2; + dtype = TYPE_INDEX_2; + break; + case 1: + destStride <<= 3; + dtype = (destOrder != 0) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; + break; + default: + return; + } + dpr = destY * destStride + destX; + + dp = dpr; + sp = spr; + destPaletteSize = destNumColors; + + RGBIndexTable = NgRGBIndexCreate (); + for (dy = destHeight; dy > 0; --dy, sp = spr += srcStride, dp = dpr += destStride) + { + for (dx = destWidth; dx > 0; --dx, dp += 1) + { + /*** READ NEXT PIXEL ASSUMING BGR ordering (BMP format) ***/ + b = srcData[sp]; + g = srcData[sp+1]; + r = srcData[sp+2]; + sp += 3; + + /*** MAP COLOR TO THE PALETTE ***/ + storedIndex = NgRGBIndexGet (RGBIndexTable, r, g, b); + if (storedIndex >= 0) + { + index = (UBYTE1) storedIndex; + } else + { + for (j = 0, minDistance = 0x7fffffff; j < destPaletteSize; ++j) + { + dr = (destColors[j*3] & 0xff) - r; + dg = (destColors[j*3+1] & 0xff) - g; + db = (destColors[j*3+2] & 0xff) - b; + distance = dr * dr + dg * dg + db * db; + if (distance < minDistance) + { + index = (UBYTE1)j; + if (distance == 0) break; + minDistance = distance; + } + } + NgRGBIndexSet (RGBIndexTable, r, g, b, index); + } + + /*** WRITE NEXT PIXEL ***/ + switch (dtype) { + case TYPE_INDEX_8: + destData[dp] = (UBYTE1) index; + break; + case TYPE_INDEX_4: + if ((dp & 1) != 0) destData[dp >> 1] = ((destData[dp >> 1] & 0xf0) | index); + else destData[dp >> 1] = ((destData[dp >> 1] & 0x0f) | (index << 4)); + break; + case TYPE_INDEX_2: + { + int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = ((destData[dp >> 2] & ~(0x03 << shift)) | (index << shift)); + } break; + case TYPE_INDEX_1_MSB: + { + int shift = 7 - (dp & 7); + destData[dp >> 3] = ((destData[dp >> 3] & ~(0x01 << shift)) | (index << shift)); + } break; + case TYPE_INDEX_1_LSB: + { + int shift = dp & 7; + destData[dp >> 3] = ((destData[dp >> 3] & ~(0x01 << shift)) | (index << shift)); + } break; + } + } + } + NgRGBIndexFree (RGBIndexTable); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.h b/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.h new file mode 100644 index 000000000..2b0f9f4af --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgImageData.h @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef __NG_IMAGEDATA_H +#define __NG_IMAGEDATA_H + +/** + * Type ng_bitmap_image_t (C version of SWT ImageData) + * + * Unlike ImageData, ng_bitmap_image_t and all its api are 'internal'. + * The api marked 'public' is in the sense that it can be used + * by the rest of the native graphic library. + */ + +#include "NgCommon.h" + +typedef struct ng_bitmap_image_t ng_bitmap_image_t; + +typedef struct { + UBYTE1 blue; + UBYTE1 green; + UBYTE1 red; +} ng_color_map_entry_t; + +/* ImageData in SWT expects RGB not BGR */ +enum { RedOffset=0, GreenOffset=1, BlueOffset=2 }; + +struct ng_bitmap_image_t { + /* Width in bytes of each row */ + UBYTE4 row_width; + /* Number of bits per pixel (depth) 1, 2, 4, 8, 16 or 24 */ + UBYTE4 bit_count; + UBYTE4 image_width; + UBYTE4 image_height; + /* image data + * 24-bit images, 3 bytes per pixel representing RGB values + * 32 bit images, 4 bytes per pixel representing RGB values + one wasted byte + * 16 bit images, 2 bytes per pixel + * rest (1, 2, 4, 8): index into color map + */ + UBYTE1 *image_data; + /* alpha data (either NULL or of size image_width*image_height) */ + UBYTE1 *alpha_data; + /* transparent pixel - default is -1 which means no transparent pixel */ + BYTE4 transparent_pixel; + /* number of entries in color map */ + UBYTE4 color_count; + ng_color_map_entry_t *color_map; +}; + +/************************************************ + * Public API ng_bitmap_image_t + ************************************************/ + +/** + * Init an image + */ +void NgBitmapImageInit (ng_bitmap_image_t *); + +/** + * Dispose the resources allocated by the image. + */ +void NgBitmapImageFree (ng_bitmap_image_t *); + +/** + * Access start of image data + * return: a pointer to an array of UBYTE1 of size image_row * image_width + * signature: UBYTE1 *NgBitmapImageImageData (ng_bitmap_image_t *image) + */ +#define NgBitmapImageImageData(image) ((image)->image_data) + +/** + * signature: UBYTE4 NgBitmapImageWidth (ng_bitmap_image_t *image) + */ +#define NgBitmapImageWidth(image) ((image)->image_width) + +/** + * signature: UBYTE4 NgBitmapImageHeight (ng_bitmap_image_t *image) + */ +#define NgBitmapImageHeight(image) ((image)->image_height) + +/** + * signature: UBYTE4 NgBitmapImageBitCount (ng_bitmap_image_t *image) + */ +#define NgBitmapImageBitCount(image) ((image)->bit_count) + +/** + * signature: UBYTE4 NgBitmapImageColorCount (ng_bitmap_image_t *image) + */ +#define NgBitmapImageColorCount(image) ((image)->color_count) + +/** + * Access a row of the image + * row: a value which must be between 0 and image_height-1 + * return: a pointer to the desired row, which is an array of size row_width + * signature: UBYTE1 *NgBitmapImageGetRow (ng_bitmap_image_t *image, UBYTE4 row) + */ +#define NgBitmapImageGetRow(image, row) (&image->image_data[row * image->row_width]) + +/** + * signature: UBYTE4 NgBitmapImageBytesPerRow (ng_bitmap_image_t *image) + */ +#define NgBitmapImageBytesPerRow(image) ((image)->row_width) + +/** + * Retrieve an entry from the color map + * index: a value which must be between 0 and color_count-1 + */ +ng_color_map_entry_t *NgBitmapImageColorMap (ng_bitmap_image_t *, UBYTE4 index); + +/** + * Get the value of the transparent pixel + * signature: BYTE4 NgBitmapImageGetTransparent (ng_bitmap_image_t *image) + */ +#define NgBitmapImageGetTransparent(image) ((image)->transparent_pixel) + +/** + * Get the alpha data + * signature: UBYTE1 *NgBitmapImageGetAlpha (ng_bitmap_image_t* image) + */ +#define NgBitmapImageGetAlpha(image) ((image)->alpha_data) + +void NgBitmapImageBlitDirectToDirect( + UBYTE1 *srcData, BYTE4 srcStride, + BYTE4 srcWidth, BYTE4 srcHeight, + UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder, + UBYTE4 destRedMask, UBYTE4 destGreenMask, UBYTE4 destBlueMask); + +/* Size of hash table used in NgBitmapImageBlitDirectToPalette */ +#define RGBIndexTableSize 103 + +typedef struct { + UBYTE1 isSet; + UBYTE1 blue; + UBYTE1 green; + UBYTE1 red; + UBYTE1 index; +} ng_palette_bucket_t; + +void NgBitmapImageBlitDirectToPalette( + UBYTE1 *srcData, BYTE4 srcStride, + BYTE4 srcWidth, BYTE4 srcHeight, + UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder, + UBYTE1 *destColors, int destNumColors); + +/************************************************ + * Private API ng_bitmap_image_t + ************************************************/ + +/* Number of bytes to round each row to */ +#define RowRounding 4 + +void NgBitmapImageInitialize (ng_bitmap_image_t *); +void NgBitmapImageClearData (ng_bitmap_image_t *); + +void NgBitmapImageSetSize(ng_bitmap_image_t *, + UBYTE4 color_count, + UBYTE4 bits, + UBYTE4 width, + UBYTE4 height); + +#endif /* NG_IMAGEDATA_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.c b/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.c new file mode 100644 index 000000000..57989f649 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.c @@ -0,0 +1,367 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include "NgCommon.h" +#include "NgWinBMPFileFormat.h" + +#define BMPHeaderFixedSize 40 + +BYTE4 decompressRLE4Data(BYTE1 *src, BYTE4 numBytes, BYTE4 stride, BYTE1 *dest, BYTE4 destSize) +{ + BYTE4 sp = 0; + BYTE4 se = numBytes; + BYTE4 dp = 0; + BYTE4 de = destSize; + BYTE4 x = 0, y = 0; + BYTE4 i; + while (sp < se) + { + int len = src[sp] & 0xFF; + sp++; + if (len == 0) + { + len = src[sp] & 0xFF; + sp++; + switch (len) + { + case 0: /* end of line */ + y++; + x = 0; + dp = y * stride; + if (dp >= de) + return -1; + break; + case 1: /* end of bitmap */ + return 1; + case 2: /* delta */ + x += src[sp] & 0xFF; + sp++; + y += src[sp] & 0xFF; + sp++; + dp = y * stride + x / 2; + if (dp >= de) + return -1; + break; + default: /* absolute mode run */ + if ((len & 1) != 0) /* odd run lengths not currently supported */ + return -1; + x += len; + len = len / 2; + if (len > (se - sp)) + return -1; + if (len > (de - dp)) + return -1; + for (i = 0; i < len; i++) + { + dest[dp] = src[sp]; + dp++; + sp++; + } + if ((sp & 1) != 0) + sp++; /* word align sp? */ + break; + } + } else + { + BYTE1 theByte; + if ((len & 1) != 0) + return -1; + x += len; + len = len / 2; + theByte = src[sp]; + sp++; + if (len > (de - dp)) + return -1; + for (i = 0; i < len; i++) + { + dest[dp] = theByte; + dp++; + } + } + } + return 1; +} + +BYTE4 decompressRLE8Data(BYTE1 *src, BYTE4 numBytes, BYTE4 stride, BYTE1 *dest, BYTE4 destSize) +{ + BYTE4 sp = 0; + BYTE4 se = numBytes; + BYTE4 dp = 0; + BYTE4 de = destSize; + BYTE4 x = 0, y = 0; + BYTE4 i; + while (sp < se) { + int len = src[sp] & 0xFF; + sp++; + if (len == 0) { + len = src[sp] & 0xFF; + sp++; + switch (len) + { + case 0: /* end of line */ + y++; + x = 0; + dp = y * stride; + if (dp >= de) + return -1; + break; + case 1: /* end of bitmap */ + return 1; + case 2: /* delta */ + x += src[sp] & 0xFF; + sp++; + y += src[sp] & 0xFF; + sp++; + dp = y * stride + x; + if (dp >= de) + return -1; + break; + default: /* absolute mode run */ + if (len > (se - sp)) + return -1; + if (len > (de - dp)) + return -1; + for (i = 0; i < len; i++) + { + dest[dp] = src[sp]; + dp++; + sp++; + } + if ((sp & 1) != 0) + sp++; /* word align sp? */ + x += len; + break; + } + } else + { + BYTE1 theByte = src[sp]; + sp++; + if (len > (de - dp)) + return -1; + for (i = 0; i < len; i++) + { + dest[dp] = theByte; + dp++; + } + x += len; + } + } + return 1; +} + +ng_err_t decompressData (BYTE1 *src, BYTE4 numBytes, BYTE1 *dest, BYTE4 destSize, BYTE4 stride, BYTE4 cmp) +{ + if (cmp == 1) + { + /* BMP_RLE8_COMPRESSION */ + if (decompressRLE8Data (src, numBytes, stride, dest, destSize) <= 0) + return NgError (ERR_NG, "Error decompressRLE8Data failed"); + } else if (cmp == 2) + { + /* BMP_RLE4_COMPRESSION */ + if (decompressRLE4Data (src, numBytes, stride, dest, destSize) <= 0) + return NgError (ERR_NG, "Error decompressRLE4Data failed"); + } else + { + return NgError (ERR_NG, "Error decompressData failed - unsupported compression"); + } + return ERR_OK; +} + +void flipScanLines(BYTE1 *data, BYTE4 numBytes, int stride, int height) +{ + BYTE4 i1 = 0; + BYTE4 i2 = (height - 1) * stride; + BYTE4 i, index; + for (i = 0; i < height / 2; i++) + { + for (index = 0; index < stride; index++) + { + BYTE1 b = data[index + i1]; + data[index + i1] = data[index + i2]; + data[index + i2] = b; + } + i1 += stride; + i2 -= stride; + } +} + +/** + * BmpDecoderReadImage + * + * Decode the content of a bmp file. + * + * in : the input stream + * image : a pointer to a ng_bitmap_image_t + * + * return: ERR_OK if the image was correctly built from the input stream + * ERR_NG otherwise. + */ +ng_err_t NgBmpDecoderReadImage (ng_stream_t *in, ng_bitmap_image_t *image) +{ + BYTE4 *fileHeader = (BYTE4*) NgMalloc (5 * sizeof(BYTE4)); + BYTE1 *infoHeader, *data; + BYTE4 width, height, stride, dataSize, cmp, pos; + BYTE2 depth; + BYTE2 d0; + + NgStreamRead (in, (char *) &d0, sizeof(BYTE2)); + fileHeader[0] = (BYTE4)LittleEndianToSystemUBYTE2(d0); + NgStreamRead (in, (char *) &fileHeader[1], sizeof(BYTE4)); + fileHeader[1] = LittleEndianToSystemUBYTE4(fileHeader[1]); + NgStreamRead (in, (char *) &d0, sizeof(BYTE2)); + fileHeader[2] = (BYTE4)LittleEndianToSystemUBYTE2(d0); + NgStreamRead (in, (char *) &d0, sizeof(BYTE2)); + fileHeader[3] = (BYTE4)LittleEndianToSystemUBYTE2(d0); + NgStreamRead (in, (char *) &fileHeader[4], sizeof(BYTE4)); + fileHeader[4] = LittleEndianToSystemUBYTE4(fileHeader[4]); + + if (NgStreamEof (in)) + { + NgFree (fileHeader); + return NgError (ERR_NG, "Error invalid header file"); + } + if (fileHeader[0] != 0x4D42) + { + NgFree (fileHeader); + return NgError (ERR_NG, "Error not a BMP file"); + } + + infoHeader = (BYTE1*) NgMalloc (BMPHeaderFixedSize * sizeof (BYTE1)); + NgStreamRead (in, infoHeader, BMPHeaderFixedSize * sizeof (BYTE1)); + + if (NgStreamEof (in)) + { + NgFree (fileHeader); + NgFree (infoHeader); + return NgError (ERR_NG, "Error invalid info header"); + } + + NgMemCpy (&width, &infoHeader[4], sizeof (BYTE4)); + width = LittleEndianToSystemUBYTE4(width); + + NgMemCpy (&height, &infoHeader[8], sizeof (BYTE4)); + height = LittleEndianToSystemUBYTE4(height); + + NgMemCpy (&depth, &infoHeader[14], sizeof (BYTE2)); + depth = LittleEndianToSystemUBYTE2(depth); + + stride = (width * depth + 7) / 8; + stride = (stride + 3) / 4 * 4; /* Round up to 4 byte multiple */ + + if (depth <= 8) + { + BYTE4 i, index; + BYTE1 *colors; + BYTE4 numColors; + NgMemCpy (&numColors, &infoHeader[32], sizeof (BYTE4)); + numColors = LittleEndianToSystemUBYTE4(numColors); + if (numColors == 0) + { + BYTE2 value; + NgMemCpy (&value, &infoHeader[14], sizeof (BYTE2)); + value = LittleEndianToSystemUBYTE2(value); + numColors = 1 << value; + } else + { + if (numColors > 256) + numColors = 256; + } + colors = (BYTE1*) NgMalloc (numColors * 4); + NgStreamRead (in, colors, numColors * 4); + + if (NgStreamEof (in)) + { + NgFree (fileHeader); + NgFree (infoHeader); + NgFree (colors); + return NgError (ERR_NG, "Error invalid palette info"); + } + + index = 0; + + NgBitmapImageSetSize(image, (UBYTE4)numColors, (UBYTE4)depth, + (UBYTE4)width, (UBYTE4)height); + + for (i = 0; i < numColors; i++) + { + ng_color_map_entry_t *color_map = NgBitmapImageColorMap (image, i); + color_map->blue = colors[index++]; + color_map->green = colors[index++]; + color_map->red = colors[index++]; + index++; + } + + NgFree (colors); + } else + { + /* direct - 16 and 24 bits */ + NgBitmapImageSetSize(image, 0, (UBYTE4)depth, + (UBYTE4)width, (UBYTE4)height); + } + + pos = NgStreamGetPosition (in); + if (pos < fileHeader[4]) + { + NgStreamSkip (in, fileHeader[4] - pos); + } + + dataSize = height * stride; + + data = (BYTE1*)NgBitmapImageImageData(image); + NgMemCpy (&cmp, &infoHeader[16], sizeof (BYTE4)); + cmp = LittleEndianToSystemUBYTE4(cmp); + if (cmp == 0) + { + /* BMP_NO_COMPRESSION */ + BYTE4 cnt; + cnt = NgStreamRead (in, data, dataSize); + if (cnt != dataSize) + { + NgFree (fileHeader); + NgFree (infoHeader); + return NgError (ERR_NG, "Error failed reading uncompressed data"); + } + } else + { + BYTE4 compressedSize; + BYTE1 *compressed; + BYTE4 cnt; + ng_err_t res; + NgMemCpy (&compressedSize, &infoHeader[20], sizeof (BYTE4)); + compressedSize = LittleEndianToSystemUBYTE4(compressedSize); + compressed = (BYTE1*) NgMalloc (compressedSize * sizeof (BYTE1)); + cnt = NgStreamRead (in, compressed, compressedSize); + if (cnt != compressedSize) + { + NgFree (fileHeader); + NgFree (infoHeader); + NgFree (compressed); + return NgError (ERR_NG, "Error failed reading compressed data"); + } + res = decompressData (compressed, compressedSize, data, dataSize, stride, cmp); + if (res != ERR_OK) + { + NgFree (fileHeader); + NgFree (infoHeader); + NgFree (compressed); + return NgError (res, "Error failed data decompression"); + } + + NgFree (compressed); + } + + flipScanLines(data, dataSize, stride, height); + + NgFree (fileHeader); + NgFree (infoHeader); + return ERR_OK; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.h b/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.h new file mode 100644 index 000000000..8ef7dda6b --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/NgWinBMPFileFormat.h @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef __NG_WINBMPFILEFORMAT_H +#define __NG_WINBMPFILEFORMAT_H + +/** + * BMP Decoder + */ +#include "NgCommon.h" +#include "NgImageData.h" + +/** + * BmpDecoderReadImage + * + * Decode the content of a bmp file. + * + * in : the input stream + * image : a pointer to a ng_bitmap_image_t + * + * return: ERR_OK if the image was correctly built from the input stream + * ERR_NG otherwise. + */ +ng_err_t NgBmpDecoderReadImage (ng_stream_t *in, ng_bitmap_image_t *image); + +#endif /* __NG_WINBMPFILEFORMAT_H */ diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/build.sh b/features/org.eclipse.equinox.executable.feature/library/motif/build.sh new file mode 100644 index 000000000..7bc48e7d6 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/build.sh @@ -0,0 +1,164 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2000, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Sumit Sarkar (Hewlett-Packard) +# Martin Oberhuber (Wind River) - [185734] Support building with gcc and debug +#******************************************************************************* +# +# Usage: sh build.sh [<optional switches>] [clean] +# +# where the optional switches are: +# -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +# -os <DEFAULT_OS> - default Eclipse "-os" value +# -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value +# -ws <DEFAULT_WS> - default Eclipse "-ws" value +# -java <JAVA_HOME> - java insgtall for jni headers +# +# All other arguments are directly passed to the "make" program. +# This script can also be invoked with the "clean" argument. +# +# Examples: +# sh build.sh clean +# sh build.sh -java /usr/j2se OPTFLAG=-g PICFLAG=-fpic + +cd `dirname $0` + +# Define default values for environment variables used in the makefiles. +programOutput="eclipse" +defaultOS="" +defaultOSArch="" +defaultWS="motif" +defaultJava=DEFAULT_JAVA_JNI +EXEC_DIR=../../../../../rt.equinox.binaries/org.eclipse.equinox.executable +makefile="" +javaHome="" +outputRoot="bin" +if [ "$OS" = "" ]; then + OS=`uname -s` +fi +if [ "$MODEL" = "" ]; then + MODEL=`uname -m` +fi + +case $OS in + "AIX") + makefile="make_aix.mak" + defaultOS="aix" + defaultOSArch="ppc" + defaultWS="motif" + MOTIF_HOME=/usr + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "Linux") + makefile="make_linux.mak" + defaultOS="linux" + defaultOSArch="x86" + defaultWS="motif" + X11_HOME=/usr/X11R6 + MOTIF_HOME=~/motif21 + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "SunOS") +# PATH=/usr/ccs/bin:/opt/SUNWspro/bin:$PATH + PATH=/usr/ccs/bin:/export/home/SUNWspro/bin:$PATH + [ -d /bluebird/teamswt/swt-builddir/build/JRE/SPARC/jdk1.6.0_14 ] && javaHome="/bluebird/teamswt/swt-builddir/build/JRE/SPARC/jdk1.6.0_14" + outputRoot="contributed" + export PATH + makefile="make_solaris.mak" + defaultOS="solaris" + defaultOSArch="sparc" + defaultWS="motif" + OS="Solaris" + X11_HOME=/usr/openwin + MOTIF_HOME=/usr/dt + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + "HP-UX") + X11_HOME=/usr + MOTIF_HOME=/usr + case $MODEL in + "ia64") + makefile="make_hpux_ia64_32.mak" + defaultOS="hpux" + defaultOSArch="ia64_32" + defaultWS="motif" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + javaHome="/opt/java1.5" + defaultJava=DEFAULT_JAVA_EXEC + PATH=/opt/hp-gcc/bin:$PATH + export PATH + ;; + *) + makefile="make_hpux_PA_RISC.mak" + defaultOS="hpux" + defaultOSArch="PA_RISC" + defaultWS="motif" + OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + ;; + esac + ;; + *) + echo "Unknown OS -- build aborted" + ;; +esac + +# Parse the command line arguments and override the default values. +extraArgs="" +while [ "$1" != "" ]; do + if [ "$1" = "-os" ] && [ "$2" != "" ]; then + defaultOS="$2" + shift + elif [ "$1" = "-arch" ] && [ "$2" != "" ]; then + defaultOSArch="$2" + shift + elif [ "$1" = "-ws" ] && [ "$2" != "" ]; then + defaultWS="$2" + shift + elif [ "$1" = "-output" ] && [ "$2" != "" ]; then + programOutput="$2" + shift + elif [ "$1" = "-java" ] && [ "$2" != "" ]; then + javaHome="$2" + shift + else + extraArgs="$extraArgs $1" + fi + shift +done + +# Set up environment variables needed by the makefiles. +PROGRAM_OUTPUT="$programOutput" +DEFAULT_OS="$defaultOS" +DEFAULT_OS_ARCH="$defaultOSArch" +DEFAULT_WS="$defaultWS" +JAVA_HOME=$javaHome +DEFAULT_JAVA=$defaultJava + +LIBRARY_DIR="$EXEC_DIR/../org.eclipse.equinox.launcher.$defaultWS.$defaultOS.$defaultOSArch" +OUTPUT_DIR="$EXEC_DIR/$outputRoot/$defaultWS/$defaultOS/$defaultOSArch" + +export OUTPUT_DIR PROGRAM_OUTPUT DEFAULT_OS DEFAULT_OS_ARCH DEFAULT_WS X11_HOME MOTIF_HOME JAVA_HOME DEFAULT_JAVA LIBRARY_DIR + +# If the OS is supported (a makefile exists) +if [ "$makefile" != "" ]; then + if [ "$extraArgs" != "" ]; then + make -f $makefile $extraArgs + else + echo "Building $OS launcher. Defaults: -os $DEFAULT_OS -arch $DEFAULT_OS_ARCH -ws $DEFAULT_WS" + make -f $makefile clean + case x$CC in + x*gcc*) make -f $makefile all PICFLAG=-fpic ;; + *) make -f $makefile all ;; + esac + fi +else + echo "Unknown OS ($OS) -- build aborted" +fi diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/build.xml b/features/org.eclipse.equinox.executable.feature/library/motif/build.xml new file mode 100644 index 000000000..990298e64 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/build.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="install"/> + </exec> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.c b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.c new file mode 100644 index 000000000..049cb7837 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.c @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + *******************************************************************************/ + + +/* UNIX/Motif specific logic for displaying the splash screen. */ +#include "eclipseCommon.h" +#include "eclipseMozilla.h" +#include "eclipseMotif.h" +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include "NgImage.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#ifdef SOLARIS +#include <sys/filio.h> +#endif +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <stdlib.h> + +/* Global Variables */ +char* defaultVM = "java"; +char* vmLibrary = "libjvm.so"; +char* shippedVMDir = "jre/bin/"; + +/* Define the special arguments for the various Java VMs. */ +static char* argVM_JAVA[] = { NULL }; +#if AIX +static char* argVM_JAVA_AIX131[] = { "-Xquickstart", NULL }; +#endif +static char* argVM_J9[] = { "-jit", "-mca:1024", "-mco:1024", "-mn:256", "-mo:4096", + "-moi:16384", "-mx:262144", "-ms:16", "-mr:16", NULL }; + +/* Define local variables for the main window. */ +extern XtAppContext appContext; +extern Widget topWindow; + +static pid_t jvmProcess = 0; +static int jvmExitCode; + +/* Define local variables for handling the splash window and its image. */ +static Widget shellHandle = 0; + +extern void centreShell( Widget widget, Widget expose ); + +#ifdef NETSCAPE_FIX +void fixEnvForNetscape(); +#endif /* NETSCAPE_FIX */ + +void takeDownSplashCB( Widget shell, XtPointer app_data, XtPointer widget_data ) { + shellHandle = NULL; +} + +/* Show the Splash Window + * + * Create the splash window, load the pixmap and display the splash window. + */ +int showSplash( const char* featureImage ) +{ + int x, y; + unsigned int width, height, depth, border; + ArgList args; + unsigned int nArgs; + Pixmap splashPixmap = 0; + Window root; + Display *xDisplay; + Screen* screen; + Widget scrolledHandle, drawingHandle, image; + + if (shellHandle != 0) + return 0; /* already showing splash */ + + if (initialArgv == NULL) + initialArgc = 0; + + if (initWindowSystem(&initialArgc, initialArgv, 1) != 0) { + return -1; + } + + xDisplay = motif_XtDisplay(topWindow); + screen = motif.XDefaultScreenOfDisplay( xDisplay ); + if (featureImage != NULL) + { + splashPixmap = loadBMPImage(xDisplay, screen, (char*)featureImage); + } + /* If the splash image could not be found, return an error. */ + if (splashPixmap == 0) + return ENOENT; + + motif.XGetGeometry (xDisplay, splashPixmap, &root, &x, &y, &width, &height, &border, &depth); + + /* make sure we never pass more than 20 args */ + args = malloc(10 * sizeof(Arg)); + + nArgs = 0; + /* Note that XtSetArg is a macro, and the 1st argument will be evaluated twice + * so increment nArgs on its own */ + motif_XtSetArg(args[nArgs], XmNmwmDecorations, 0); nArgs++; + motif_XtSetArg(args[nArgs], XmNtitle, getOfficialName()); nArgs++; + motif_XtSetArg(args[nArgs], XmNwidth, width); nArgs++; + motif_XtSetArg(args[nArgs], XmNheight, height); nArgs++; + shellHandle = motif.XtAppCreateShell(getOfficialName(), "", *motif.applicationShellWidgetClass, xDisplay, args, nArgs); + motif.XtAddCallback(shellHandle, XmNdestroyCallback, (XtCallbackProc) takeDownSplashCB, NULL); + + nArgs = 0; + motif_XtSetArg(args[nArgs++], XmNancestorSensitive, 1); + scrolledHandle = motif.XmCreateMainWindow(shellHandle, NULL, args, nArgs); + if(scrolledHandle == 0) + return -1; + motif.XtManageChild(scrolledHandle); + + nArgs = 0; + motif_XtSetArg(args[nArgs], XmNancestorSensitive, 1); nArgs++; + motif_XtSetArg(args[nArgs], XmNborderWidth, 0); nArgs++; + /*motif_XtSetArg(args[nArgs], XmNbackground, 0xFF00FF); nArgs++; */ + motif_XtSetArg(args[nArgs], XmNmarginWidth, 0); nArgs++; + motif_XtSetArg(args[nArgs], XmNmarginHeight, 0); nArgs++; + motif_XtSetArg(args[nArgs], XmNresizePolicy, XmRESIZE_NONE); nArgs++; + motif_XtSetArg(args[nArgs], XmNtraversalOn, 1); nArgs++; + drawingHandle = motif.XmCreateDrawingArea(scrolledHandle, NULL, args, nArgs); + if(drawingHandle == 0) + return -1; + motif.XtManageChild(drawingHandle); + + nArgs = 0; + motif_XtSetArg(args[nArgs], XmNlabelType, XmPIXMAP); nArgs++; + motif_XtSetArg(args[nArgs], XmNlabelPixmap, splashPixmap); nArgs++; + motif_XtSetArg(args[nArgs], XmNwidth, width); nArgs++; + motif_XtSetArg(args[nArgs], XmNheight, height); nArgs++; + motif_XtSetArg(args[nArgs], XmNmarginWidth, 0); nArgs++; + motif_XtSetArg(args[nArgs], XmNmarginHeight, 0); nArgs++; + image = motif.XmCreateLabelGadget ( drawingHandle, "", args, nArgs ); + motif.XtManageChild( image ); + + motif.XtRealizeWidget(shellHandle); + motif.XtSetMappedWhenManaged(shellHandle, 1); + + if(motif_XtIsTopLevelShell(shellHandle)) + motif_XtMapWidget(shellHandle); + else + motif.XtPopup(shellHandle, XtGrabNone); + + /* Centre the splash screen and display it. */ + centreShell( shellHandle, drawingHandle ); + dispatchMessages(); + + free(args); + return 0; +} + +/* Get the window system specific VM arguments */ +char** getArgVM( char* vm ) +{ + char** result; + +#ifdef AIX + char* version; +#endif + + if (isJ9VM( vm )) + return argVM_J9; + + /* Use the default arguments for a standard Java VM */ + result = argVM_JAVA; + +#ifdef AIX + /* Determine whether Java version is 1.3.1 or later */ + version = getVMVersion( vm ); + if (version != NULL) + { + if (versionCmp(version, "1.3.1") >= 0) + result = argVM_JAVA_AIX131; + free(version); + } +#endif + + return result; +} + + +jlong getSplashHandle() { + return (jlong)shellHandle; +} + +void dispatchMessages() { + XtInputMask mask; + if (appContext != NULL && motif.XtAppPending != 0) { + /* Process any outstanding messages */ + while ((mask = motif.XtAppPending(appContext)) != 0) { + motif.XtAppProcessEvent(appContext, mask); + } + } +} + +void takeDownSplash() +{ + if (shellHandle != 0) + { + motif.XtDestroyWidget( shellHandle ); + /*XFlush( XtDisplay( shellHandle ) );*/ + shellHandle = NULL; + } +} + +#ifdef NETSCAPE_FIX +extern char* findCommand( char*); +static const char* XFILESEARCHPATH = "XFILESEARCHPATH"; + +void fixEnvForNetscape() +{ + char* netscapePath = NULL; + char* netscapeResource = NULL; + char* ch; + char* envValue; + struct stat stats; + + /* If netscape appears to be installed */ + netscapePath = findCommand("netscape"); + if (netscapePath != NULL) + { + /* Look for the resource file Netscape.ad in the same directory as "netscape". */ + netscapeResource = malloc( strlen(netscapePath) + 50 ); + strcpy( netscapeResource, netscapePath ); + ch = strrchr( netscapeResource, (int) dirSeparator ); + ch =(ch == NULL ? netscapeResource : (ch+1)); + strcpy( ch, "Netscape.ad" ); + + /* If it does not exist there, try "/opt/netscape/Netscape.ad". */ + if (stat( netscapeResource, &stats ) != 0) + { + strcpy( netscapeResource, "/opt/netscape/Netscape.ad" ); + } + + /* If the resource file exists */ + if (stat( netscapeResource, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { + /* Either define XFILESEARCHPATH or append the Netscape resource file. */ + envValue = getenv( XFILESEARCHPATH ); + if (envValue == NULL) + { + ch = malloc( strlen(XFILESEARCHPATH) + strlen(netscapeResource) + 5 ); + sprintf( ch, "%s=%s", XFILESEARCHPATH, netscapeResource ); + } + else + { + ch = malloc( strlen(XFILESEARCHPATH) + strlen(netscapeResource) + + strlen(envValue) + 5 ); + sprintf( ch, "%s=%s:%s", XFILESEARCHPATH, envValue, netscapeResource ); + } + putenv( ch ); + free( ch ); + } + + /* Clean up. */ + free( netscapePath ); + free( netscapeResource ); + } +} +#endif /* NETSCAPE_FIX */ + +JavaResults* launchJavaVM( char* args[] ) +{ + JavaResults* jvmResults = NULL; + int exitCode; + +#ifdef NETSCAPE_FIX + fixEnvForNetscape(); +#endif /* NETSCAPE_FIX */ +#ifdef MOZILLA_FIX + fixEnvForMozilla(); +#endif /* MOZILLA_FIX */ + +#ifdef LINUX + { + /* put the root of eclipse on the LD_LIBRARY_PATH */ + char * ldPath = (char*)getenv(_T_ECLIPSE("LD_LIBRARY_PATH")); + if (ldPath == NULL) + ldPath = _T_ECLIPSE(""); + char * root = getProgramDir(); + if (root != NULL) { + char * newPath = malloc((strlen(root) + strlen(ldPath) + 2) * sizeof(char)); + sprintf(newPath, "%s%c%s", root, pathSeparator, ldPath); + setenv("LD_LIBRARY_PATH", newPath, 1); + free(newPath); + } + } +#endif + + /* Create a child process for the JVM. */ + jvmProcess = fork(); + if (jvmProcess == 0) + { + /* Child process ... start the JVM */ + execv( args[0], args ); + + /* The JVM would not start ... return error code to parent process. */ + /* TODO, how to distinguish this as a launch problem to the other process? */ + jvmExitCode = errno; + exit( jvmExitCode ); + } + + jvmResults = malloc(sizeof(JavaResults)); + memset(jvmResults, 0, sizeof(JavaResults)); + + /* If the JVM is still running, wait for it to terminate. */ + if (jvmProcess != 0) + { + waitpid(jvmProcess, &exitCode, 0); + /* TODO, this should really be a runResult if we could distinguish the launch problem above */ + jvmResults->launchResult = ((exitCode & 0x00ff) == 0 ? (exitCode >> 8) : exitCode); /* see wait(2) */ + } + + /* Return the exit code from the JVM. */ + return jvmResults; +} + +int reuseWorkbench(_TCHAR** filePath, int timeout) { + /* not yet implemented on motif */ + return -1; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.h b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.h new file mode 100644 index 000000000..26b807b8a --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotif.h @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#ifndef ECLIPSE_MOTIF_H +#define ECLIPSE_MOTIF_H + +#include <Xm/XmAll.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/IntrinsicP.h> +#include <X11/Intrinsic.h> +#include <X11/Shell.h> + +#ifndef NO_XINERAMA_EXTENSIONS +#include <X11/extensions/Xinerama.h> +#endif + +struct MOTIF_PTRS { +#ifndef NO_XINERAMA_EXTENSIONS + Bool (*XineramaIsActive) (Display*); + XineramaScreenInfo* (*XineramaQueryScreens) (Display*, int*); +#endif + Widget (*XmCreateDrawingArea) (Widget, String, ArgList, Cardinal); + Widget (*XmCreateLabelGadget) (Widget, char *, Arg *, Cardinal); + Widget (*XmCreateMainWindow) (Widget, char *, ArgList, Cardinal); + Widget (*XmCreateMessageDialog)(Widget, String, ArgList, Cardinal); + Widget (*XmMessageBoxGetChild) (Widget, unsigned char); + void (*XmStringFree) (XmString); + XmString (*XmStringGenerate) (XtPointer, XmStringTag, XmTextType, XmStringTag); + + void (*XtAddCallback) (Widget, String, XtCallbackProc, XtPointer); + Widget (*XtAppCreateShell) (String, String, WidgetClass, Display*, ArgList, Cardinal); + void (*XtAppNextEvent) (XtAppContext, XEvent*); + XtInputMask (*XtAppPending) (XtAppContext); + void (*XtAppProcessEvent) (XtAppContext, XtInputMask); + void (*XtDestroyWidget) (Widget); + Boolean (*XtDispatchEvent) (XEvent*); + void (*XtGetValues) (Widget, ArgList, Cardinal); + Widget (*XtInitialize) (String, String, XrmOptionDescRec*, Cardinal, int*, char**); +#ifdef AIX + Widget (*eclipseXtInitialize) (String, String, XrmOptionDescRec*, Cardinal, int*, char**); +#endif + Boolean (*XtIsManaged) (Widget); + void (*XtManageChild) (Widget); + int (*XtMapWidget) (Widget); + void (*XtPopup) (Widget, XtGrabKind); + void (*XtRealizeWidget) (Widget); + Widget (*XtSetLanguageProc) (XtAppContext, XtLanguageProc, XtPointer); + void (*XtSetMappedWhenManaged)(Widget, Boolean); + void (*XtSetValues) (Widget, ArgList, Cardinal); + void (*XtUnmanageChild) (Widget); + XtAppContext (*XtWidgetToApplicationContext) (Widget); + Window (*XtWindowOfObject) (Widget); + + Screen * (*XDefaultScreenOfDisplay)(Display*); + int (*XFree) (void*); + int (*XFlush) (Display*); + Status (*XGetGeometry) (Display*, Drawable, Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*); + int (*XMapWindow) (Display*, Window); + + char * _XmStrings; + char * XtShellStrings; + char * XtStrings; + WidgetClass *applicationShellWidgetClass; +}; + +extern struct MOTIF_PTRS motif; + +#define motif_XtDisplay XtDisplay +#define motif_XtSetArg XtSetArg +#define motif_XtWindow XtWindow +#define motif_XtIsTopLevelShell XtIsTopLevelShell +#define motif_XtIsRealized(object) (motif.XtWindowOfObject(object) != None) +#define motif_XtMapWidget(widget) motif.XMapWindow(XtDisplay(widget), XtWindow(widget)) + +#define _XmStrings motif._XmStrings +#define XtShellStrings motif.XtShellStrings +#define XtStrings motif.XtStrings + +/* macro resolves to { (void**)&motif.foo, "foo" }, use it to initialize FN_TABLEs */ +#define FN_TABLE_ENTRY(fn) { (void**)&motif.fn, #fn } +typedef struct { + void ** fnPtr; + char * fnName; +} FN_TABLE; + +extern int loadMotif(); +#endif diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifCommon.c b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifCommon.c new file mode 100644 index 000000000..93f21cbd3 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifCommon.c @@ -0,0 +1,219 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseCommon.h" +#include "eclipseOS.h" +#include "eclipseMotif.h" + +#include <locale.h> +#include <dlfcn.h> +#include <stdlib.h> + +#define ECLIPSE_ICON 401 + +char dirSeparator = '/'; +char pathSeparator = ':'; + +void centreShell( Widget widget, Widget expose ); + +/* Global Variables */ +XtAppContext appContext = 0; +Widget topWindow = 0; + +/* Define local variables for the main window. */ +static int saveArgc = 0; /* arguments after they were parsed, for window system */ +static char** saveArgv = 0; + +int motifInitialized = 0; + +/* Display a Message */ +void displayMessage( char* title, char* message ) +{ + char* displayName = NULL; + Widget msgBox = NULL; + XmString msg; + Arg arg[20]; + int nArgs; + XEvent event; + + /* If there is no associated display, or we fail to initialize Xt, just print the error and return. */ + displayName = getenv("DISPLAY"); + if ( displayName == NULL || strlen(displayName) == 0 || + (topWindow == 0 && initWindowSystem( &saveArgc, saveArgv, 1 ) != 0) ) + { + printf("%s:\n%s\n", title, message); + return; + } + msg = motif.XmStringGenerate( message, NULL, XmCHARSET_TEXT, NULL ); + + /* Output a simple message box. */ + nArgs = 0; + + motif_XtSetArg( arg[ nArgs ], XmNdialogType, XmDIALOG_MESSAGE ); nArgs++; + motif_XtSetArg( arg[ nArgs ], XmNtitle, title ); nArgs++; + motif_XtSetArg( arg[ nArgs ], XmNmessageString, msg ); nArgs++; + msgBox = motif.XmCreateMessageDialog( topWindow, getOfficialName(), arg, nArgs ); + + motif.XtUnmanageChild( motif.XmMessageBoxGetChild( msgBox, XmDIALOG_CANCEL_BUTTON ) ); + motif.XtUnmanageChild( motif.XmMessageBoxGetChild( msgBox, XmDIALOG_HELP_BUTTON ) ); + motif.XtManageChild( msgBox ); + centreShell( msgBox, msgBox ); + if (msg != 0) motif.XmStringFree (msg); + + /* Wait for the OK button to be pressed. */ + while (motif_XtIsRealized( msgBox ) && motif.XtIsManaged( msgBox )) + { + motif.XtAppNextEvent( appContext, &event ); + motif.XtDispatchEvent( &event ); + } + motif.XtDestroyWidget( msgBox ); +} + +/* Initialize Window System + * + * Initialize the Xt and Xlib. + */ +int initWindowSystem( int* pArgc, char* argv[], int showSplash ) +{ + Arg arg[20]; + char * officialName; + + if(motifInitialized == 1) + return 0; + + if (loadMotif() != 0) + return -1; + + /* Save the arguments in case displayMessage() is called in the main launcher. */ + if (saveArgv == 0) + { + saveArgc = *pArgc; + saveArgv = argv; + } + + officialName = getOfficialName(); + if (officialName != NULL) + setenv("RESOURCE_NAME", getOfficialName(), 1); + + /* Create the top level shell that will not be used other than + to initialize the application. + */ +#ifdef AIX + topWindow = motif.eclipseXtInitialize(NULL, officialName, NULL, 0, pArgc, argv); +#else + topWindow = motif.XtInitialize(NULL, officialName, NULL, 0, pArgc, argv); +#endif + appContext = motif.XtWidgetToApplicationContext(topWindow); + motif.XtSetLanguageProc (appContext, NULL, NULL); + motif_XtSetArg( arg[ 0 ], XmNmappedWhenManaged, False ); + motif.XtSetValues( topWindow, arg, 1 ); + motif.XtRealizeWidget( topWindow ); + motifInitialized = 1; + return 0; +} + +/* Centre the shell on the screen. */ +void centreShell( Widget widget, Widget expose ) +{ + XtAppContext context; + XEvent event; + Arg arg[20]; + int nArgs; + Position x, y; + Dimension width, height; + Screen* screen; + int waiting; + short screenWidth, screenHeight; + +#ifndef NO_XINERAMA_EXTENSIONS + Display* display; + int monitorCount; + XineramaScreenInfo* info; +#endif + + /* Realize the shell to calculate its width/height. */ + motif.XtRealizeWidget( widget ); + + /* Get the desired dimensions of the shell. */ + nArgs = 0; + motif_XtSetArg( arg[ nArgs ], XmNwidth, &width ); nArgs++; + motif_XtSetArg( arg[ nArgs ], XmNheight, &height ); nArgs++; + motif_XtSetArg( arg[ nArgs ], XmNscreen, &screen ); nArgs++; + motif.XtGetValues( widget, arg, nArgs ); + + screenWidth = screen->width; + screenHeight = screen->height; +#ifndef NO_XINERAMA_EXTENSIONS + display = motif_XtDisplay( widget ); + if (motif.XineramaIsActive != 0 && motif.XineramaIsActive( display )) { + info = motif.XineramaQueryScreens( display, &monitorCount ); + if (info != 0) { + if (monitorCount > 1) { + screenWidth = info->width; + screenHeight = info->height; + } + motif.XFree (info); + } + } +#endif + + /* Calculate the X and Y position for the shell. */ + x = (screenWidth - width) / 2; + y = (screenHeight - height) / 2; + + /* Set the new shell position and display it. */ + nArgs = 0; + motif_XtSetArg( arg[ nArgs ], XmNx, x ); nArgs++; + motif_XtSetArg( arg[ nArgs ], XmNy, y ); nArgs++; + motif.XtSetValues( widget, arg, nArgs ); + motif_XtMapWidget( widget ); + + /* Wait for an expose event on the desired widget. This wait loop is required when + * the startVM command fails and the message box is created before the splash + * window is displayed. Without this wait, the message box sometimes appears + * under the splash window and the user cannot see it. + */ + context = motif.XtWidgetToApplicationContext( widget ); + waiting = True; + while (waiting) + { + motif.XtAppNextEvent( context, &event ); + if (event.xany.type == Expose && event.xany.window == motif_XtWindow( expose )) + { + waiting = False; + } + motif.XtDispatchEvent( &event ); + } + motif.XFlush( motif_XtDisplay( widget ) ); +} + +/* Load the specified shared library + */ +void * loadLibrary( char * library ){ + void * result= dlopen(library, RTLD_LAZY); + if(result == 0) + printf("%s\n",dlerror()); + return result; +} + +/* Unload the shared library + */ +void unloadLibrary( void * handle ){ + dlclose(handle); +} + +/* Find the given symbol in the shared library + */ +void * findSymbol( void * handle, char * symbol ){ + return dlsym(handle, symbol); +} + diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifInit.c b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifInit.c new file mode 100644 index 000000000..c9ca22e7c --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifInit.c @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include "eclipseMotif.h" +#include "eclipseCommon.h" +#include <dlfcn.h> +#include <stdlib.h> + +struct MOTIF_PTRS motif; + +/* need to undef these so the FN_TABLE works ok */ +#undef _XmStrings +#undef XtShellStrings +#undef XtStrings + +/* functions from libXm */ +static FN_TABLE xmFunctions[] = { FN_TABLE_ENTRY(XmCreateDrawingArea), + FN_TABLE_ENTRY(XmCreateLabelGadget), + FN_TABLE_ENTRY(XmCreateMainWindow), + FN_TABLE_ENTRY(XmCreateMessageDialog), + FN_TABLE_ENTRY(XmMessageBoxGetChild), + FN_TABLE_ENTRY(XmStringFree), + FN_TABLE_ENTRY(XmStringGenerate), + FN_TABLE_ENTRY(_XmStrings), /* not a function */ + { NULL, NULL } + }; + +/* functions from libXt */ +static FN_TABLE xtFunctions[] = { FN_TABLE_ENTRY(XtAddCallback), + FN_TABLE_ENTRY(XtAppCreateShell), + FN_TABLE_ENTRY(XtAppNextEvent), + FN_TABLE_ENTRY(XtAppPending), + FN_TABLE_ENTRY(XtAppProcessEvent), + FN_TABLE_ENTRY(XtDestroyWidget), + FN_TABLE_ENTRY(XtDispatchEvent), + FN_TABLE_ENTRY(XtGetValues), +#ifndef AIX + FN_TABLE_ENTRY(XtInitialize), +#endif + FN_TABLE_ENTRY(XtIsManaged), + FN_TABLE_ENTRY(XtManageChild), + FN_TABLE_ENTRY(XtMapWidget), + FN_TABLE_ENTRY(XtPopup), + FN_TABLE_ENTRY(XtRealizeWidget), + FN_TABLE_ENTRY(XtSetLanguageProc), + FN_TABLE_ENTRY(XtSetMappedWhenManaged), + FN_TABLE_ENTRY(XtSetValues), + FN_TABLE_ENTRY(XtUnmanageChild), + FN_TABLE_ENTRY(XtWidgetToApplicationContext), + FN_TABLE_ENTRY(XtWindowOfObject), + FN_TABLE_ENTRY(XtShellStrings), /* not a function */ + FN_TABLE_ENTRY(XtStrings), /* not a function */ + FN_TABLE_ENTRY(applicationShellWidgetClass), /* not a function */ + { NULL, NULL } + }; + +#ifdef AIX +static FN_TABLE shimFunctions[] = { FN_TABLE_ENTRY(eclipseXtInitialize), {NULL, NULL} }; +#endif + +/* functions from libX11 */ +static FN_TABLE x11Functions[] = { FN_TABLE_ENTRY(XDefaultScreenOfDisplay), + FN_TABLE_ENTRY(XFree), + FN_TABLE_ENTRY(XFlush), + FN_TABLE_ENTRY(XGetGeometry), + FN_TABLE_ENTRY(XMapWindow), + { NULL, NULL } + }; + +#ifndef NO_XINERAMA_EXTENSIONS +static FN_TABLE xinFunctions[] = { FN_TABLE_ENTRY(XineramaIsActive), + FN_TABLE_ENTRY(XineramaQueryScreens), + { NULL, NULL } + }; +#endif + +static int loadMotifSymbols( void * library, FN_TABLE * table) { + int i = 0; + void * fn; + for (i = 0; table[i].fnName != NULL; i++) { + fn = findSymbol(library, table[i].fnName); + if (fn != 0) { + *(table[i].fnPtr) = fn; + } else { + *(table[i].fnPtr) = 0; + return -1; + } + } + return 0; +} + +#ifdef AIX +void * loadMotifShimLibrary() { + if (eclipseLibrary != NULL) { + /* library is the normal eclipse_<ver>.so, look for libeclipse-motif.so beside it */ + _TCHAR* eclipseMotifLib = _T_ECLIPSE("libeclipse-motif.so"); + _TCHAR* path = strdup(eclipseLibrary); + _TCHAR* c = strrchr(path, '/'); + if (c == NULL) { + free(path); + return NULL; + } + + *c = 0; + c = malloc((strlen(path) + 2 + strlen(eclipseMotifLib)) * sizeof(char)); + _stprintf(c, _T_ECLIPSE("%s/%s"), path, eclipseMotifLib); + free(path); + return dlopen(c, RTLD_LAZY); + } + return 0; +} +#endif + +int loadMotif() { + void * xmLib = NULL, *xtLib = NULL, *x11Lib = NULL, *xinLib = NULL; +#ifdef AIX + void * motifShim = NULL; +#endif + char * path = getProgramDir(); + int dlFlags = RTLD_LAZY; + + /* initialize ptr struct to 0's */ + memset(&motif, 0, sizeof(struct MOTIF_PTRS)); + +#ifndef AIX + if (path != NULL) { + /* look for libXm first in the root of eclipse */ + char * lib = malloc((strlen(path) + strlen(_T_ECLIPSE(XM_LIB)) + 2) * sizeof(char)); + sprintf( lib, "%s%c%s", path, dirSeparator, XM_LIB); + xmLib = dlopen(lib, dlFlags); + free(lib); + } +#else + dlFlags |= RTLD_MEMBER; + motifShim = loadMotifShimLibrary(); + if (motifShim == NULL) + return -1; +#endif + + if (xmLib == NULL) { + xmLib = dlopen(XM_LIB, dlFlags); + } + + if (xmLib == NULL) { + /* bail now, don't load the others, libXm must be loaded first, so leave things for + * swt to do later */ + return -1; + } + + xtLib = dlopen(XT_LIB, dlFlags); + x11Lib = dlopen(X11_LIB, dlFlags); + + /* printf("XmLib: %s: %x\nXtLib: %s: %x\nX11Lib:%s, %x\n", XM_LIB, xmLib, XT_LIB, xtLib, X11_LIB, x11Lib);*/ +#ifndef NO_XINERAMA_EXTENSIONS + /* don't fail without Xinerama */ + xinLib = dlopen(XIN_LIB, dlFlags); + if (xinLib != NULL) + loadMotifSymbols(xinLib, xinFunctions); +#endif + if( xtLib == NULL || x11Lib == NULL) + return -1; + + if (loadMotifSymbols(xmLib, xmFunctions) != 0) return -1; + if (loadMotifSymbols(xtLib, xtFunctions) != 0) return -1; + if (loadMotifSymbols(x11Lib, x11Functions) != 0) return -1; +#ifdef AIX + if (loadMotifSymbols(motifShim, shimFunctions) !=0) return -1; +#endif + + return 0; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifShim.c b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifShim.c new file mode 100644 index 000000000..2648ec65e --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/eclipseMotifShim.c @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +#include <X11/X.h> +#include <X11/Xlib.h> +#include <Xm/XmAll.h> + +Widget eclipseXtInitialize(String shellName, String appClass, XrmOptionDescRec* options, Cardinal numOptions, int* argc, char** argv) { + return XtInitialize(shellName, appClass, options, numOptions, argc, argv); +} diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/make_aix.mak b/features/org.eclipse.equinox.executable.feature/library/motif/make_aix.mak new file mode 100644 index 000000000..1d4689e1c --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/make_aix.mak @@ -0,0 +1,104 @@ +#******************************************************************************* +# Copyright (c) 2000, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the AIX/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files +# JAVA_JNI - the full path to the java jni header files + +PROGRAM_OUTPUT=eclipse +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so +SHIM=libeclipse-motif.so + +CC = gcc +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o +SHIM_OBJS = eclipseMotifShim.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseMotifCommon.o eclipseMotifInit.o +DLL_OBJS = eclipse.o eclipseMotif.o eclipseUtil.o eclipseJNI.o eclipseShm.o eclipseNix.o\ + NgCommon.o NgImage.o NgImageData.o NgWinBMPFileFormat.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -L$(MOTIF_HOME)/lib -ldl +SHIM_LIBS = -L$(MOTIF_HOME)/lib -lXm -lXt -lX11 +MOTIF_LIBS = -DXM_LIB="\"libXm.a(shr_32.o)\"" -DXT_LIB="\"libXt.a(shr4.o)\"" -DX11_LIB="\"libX11.a(shr4.o)\"" +LFLAGS = -G -bnoentry -bexpall -lm -lc_r -lC_r +CFLAGS = -O -s \ + -DMOTIF \ + -DNO_XINERAMA_EXTENSIONS \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + $(MOTIF_LIBS) \ + -DAIX \ + -I./ \ + -I../ \ + -I$(MOTIF_HOME)/include \ + -I/usr/java5/include + +all: $(EXEC) $(DLL) $(SHIM) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseShm.o: ../eclipseShm.c ../eclipseShm.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -Wl,-bM:UR -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + sedmgr -c exempt $(EXEC) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + ld $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +$(SHIM): $(SHIM_OBJS) + ld $(LFLAGS) -o $(SHIM) $(SHIM_OBJS) $(SHIM_LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(SHIM) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(DLL) $(SHIM) $(SHIM_OBJS) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_PA_RISC.mak b/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_PA_RISC.mak new file mode 100644 index 000000000..2552b56fc --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_PA_RISC.mak @@ -0,0 +1,94 @@ +#******************************************************************************* +# Copyright (c) 2000, 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the HPUX/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files + +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +endif + +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseMotifCommon.o +DLL_OBJS = eclipse.o eclipseMotif.o eclipseUtil.o eclipseJNI.o eclipseNix.o eclipseShm.o\ + NgCommon.o NgImage.o NgImageData.o NgWinBMPFileFormat.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -L$(MOTIF_HOME)/lib -L$(X11_HOME)/lib -lXm -lXt -lX11 -lpthread +LFLAGS = -shared -Wl,--export-dynamic +CFLAGS = -O -s \ + -DNO_XINERAMA_EXTENSIONS \ + -DNETSCAPE_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + +Z \ + -I./ \ + -I../ \ + -I$(MOTIF_HOME)/include \ + -I$(X11_HOME)/include \ + -I$(JAVA_JNI) \ + +DAportable + +all: $(EXEC) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c ../eclipseMain.c -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(DLL) $(OUTPUT_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_ia64_32.mak b/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_ia64_32.mak new file mode 100644 index 000000000..92667dac0 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/make_hpux_ia64_32.mak @@ -0,0 +1,101 @@ +#******************************************************************************* +# Copyright (c) 2000, 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Sumit Sarkar (Hewlett-Packard) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the HPUX/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files + +#ifeq ($(PROGRAM_OUTPUT),) +# PROGRAM_OUTPUT=eclipse +#endif + +DEFAULT_JAVA=DEFAULT_JAVA_EXEC +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +CC=gcc +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseMotifCommon.o eclipseMotifInit.o +DLL_OBJS = eclipse.o eclipseMotif.o eclipseUtil.o eclipseJNI.o eclipseNix.o eclipseShm.o \ + NgCommon.o NgImage.o NgImageData.o NgWinBMPFileFormat.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -L$(MOTIF_HOME)/lib -L$(X11_HOME)/lib -lpthread +MOTIF_LIBS = -DXM_LIB="\"libXm.so.1\"" -DXT_LIB="\"libXt.so.1\"" -DX11_LIB="\"libX11.so.1\"" +LFLAGS = -shared -static-libgcc +# -Wl,--export-dynamic +CFLAGS = -O -s \ + -DNO_XINERAMA_EXTENSIONS \ + -DNETSCAPE_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -D$(DEFAULT_JAVA) \ + -DHPUX \ + $(MOTIF_LIBS) \ + -I./ \ + -I../ \ + -I$(MOTIF_HOME)/include \ + -I$(X11_HOME)/include \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/hp-ux + +all: $(EXEC) $(DLL) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c ../eclipseMain.c -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/make_linux.mak b/features/org.eclipse.equinox.executable.feature/library/motif/make_linux.mak new file mode 100644 index 000000000..a29d1b9b6 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/make_linux.mak @@ -0,0 +1,108 @@ +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the Linux/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files +# JAVA_HOME - JAVA_HOME for the java jni header files + +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +endif + +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +ifeq ($(DEFAULT_JAVA),) + DEFAULT_JAVA=DEFAULT_JAVA_JNI +endif + +# Define the object modules to be compiled and flags. +CC?=gcc +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseMotifCommon.o eclipseMotifInit.o +DLL_OBJS = eclipse.o eclipseMotif.o eclipseUtil.o eclipseJNI.o eclipseMozilla.o eclipseShm.o eclipseNix.o \ + NgCommon.o NgImage.o NgImageData.o NgWinBMPFileFormat.o + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -Xlinker -rpath -Xlinker . -L$(MOTIF_HOME)/lib -L$(X11_HOME)/lib -lpthread -ldl +MOTIF_LIBS = -DXM_LIB="\"libXm.so.2\"" -DXT_LIB="\"libXt.so.6\"" -DX11_LIB="\"libX11.so.6\"" -DXIN_LIB="\"libXinerama.so.1\"" +LFLAGS = -shared -fpic -Wl,--export-dynamic +CFLAGS = -g -s -Wall \ + -DLINUX \ + -DMOTIF \ + -DMOZILLA_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + $(MOTIF_LIBS) \ + -D$(DEFAULT_JAVA)\ + -fPIC \ + -I./ \ + -I../ \ + -I$(MOTIF_HOME)/include \ + -I$(X11_HOME)/include \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux + +all: $(EXEC) $(DLL) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseMozilla.o: ../eclipseMozilla.c ../eclipseMozilla.h ../eclipseOS.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseShm.o: ../eclipseShm.c ../eclipseShm.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/motif/make_solaris.mak b/features/org.eclipse.equinox.executable.feature/library/motif/make_solaris.mak new file mode 100644 index 000000000..3438ce369 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/motif/make_solaris.mak @@ -0,0 +1,104 @@ +#******************************************************************************* +# Copyright (c) 2000, 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Martin Oberhuber (Wind River) - [185734] Support building with gcc and debug +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the Solaris/Motif eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# X11_HOME - the full path to X11 header files +# MOTIF_HOME - the full path to Motif header files +# JAVA_HOME - path to java for JNI headers + +#ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse +#endif + +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).so + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseMotifCommon.o eclipseMotifInit.o +DLL_OBJS = eclipse.o eclipseMotif.o eclipseUtil.o eclipseJNI.o eclipseShm.o eclipseNix.o\ + NgCommon.o NgImage.o NgImageData.o NgWinBMPFileFormat.o +PICFLAG = -K PIC +# Optimize and remove all debugging information by default +OPTFLAG = -O -s +# OPTFLAG = -g + +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +LIBS = -L$(MOTIF_HOME)/lib -L$(X11_HOME)/lib -lintl -lthread -ldl -lc +MOTIF_LIBS = -DXM_LIB="\"libXm.so.4\"" -DXT_LIB="\"libXt.so.4\"" -DX11_LIB="\"libX11.so.4\"" -DXIN_LIB="\"libXinerama.so.1\"" +#LFLAGS = -shared -Wl,--export-dynamic +LFLAGS = -G +CFLAGS =$(OPTFLAG) \ + -DSOLARIS \ + $(PICFLAG) \ + -DNO_XINERAMA_EXTENSIONS \ + -DNETSCAPE_FIX \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + $(MOTIF_LIBS) \ + -I./ \ + -I../ \ + -I$(MOTIF_HOME)/include \ + -I$(X11_HOME)/include \ + -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/solaris + +all: $(EXEC) $(DLL) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipseMain.o: ../eclipseMain.c ../eclipseUnicode.h ../eclipseCommon.h + $(CC) $(CFLAGS) -c ../eclipseMain.c -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h ../eclipseCommon.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseCommon.o: ../eclipseCommon.c ../eclipseCommon.h ../eclipseUnicode.h + $(CC) $(CFLAGS) -c ../eclipseCommon.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +eclipseJNI.o: ../eclipseJNI.c ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.h + $(CC) $(CFLAGS) -c ../eclipseJNI.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +eclipseNix.o: ../eclipseNix.c + $(CC) $(CFLAGS) -c ../eclipseNix.c -o $@ + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + $(CC) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(LFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + cp $(DLL) $(LIBRARY_DIR) + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) + +clean: + rm -f $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/photon/.cvsignore b/features/org.eclipse.equinox.executable.feature/library/photon/.cvsignore new file mode 100644 index 000000000..5535df034 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/photon/.cvsignore @@ -0,0 +1,2 @@ +*.o +eclipse diff --git a/features/org.eclipse.equinox.executable.feature/library/photon/build.sh b/features/org.eclipse.equinox.executable.feature/library/photon/build.sh new file mode 100644 index 000000000..43ef9b167 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/photon/build.sh @@ -0,0 +1,79 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2000, 2006 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +# +# Usage: sh build.sh [<optional switches>] [clean] +# +# where the optional switches are: +# -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +# -os <DEFAULT_OS> - default Eclipse "-os" value +# -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value +# -ws <DEFAULT_WS> - default Eclipse "-ws" value +# +# +# This script can also be invoked with the "clean" argument. + +cd `dirname $0` + +# Define default values for environment variables used in the makefiles. +programOutput="eclipse" +defaultOS="qnx" +defaultOSArch="x86" +defaultWS="photon" +makefile="make_qnx.mak" +if [ "$OS" = "" ]; then + OS=`uname -s` +fi + +# Parse the command line arguments and override the default values. +extraArgs="" +while [ "$1" != "" ]; do + if [ "$1" = "-os" ] && [ "$2" != "" ]; then + defaultOS="$2" + shift + elif [ "$1" = "-arch" ] && [ "$2" != "" ]; then + defaultOSArch="$2" + shift + elif [ "$1" = "-ws" ] && [ "$2" != "" ]; then + defaultWS="$2" + shift + elif [ "$1" = "-output" ] && [ "$2" != "" ]; then + programOutput="$2" + shift + else + extraArgs="$extraArgs $1" + fi + shift +done + +# Set up environment variables needed by the makefiles. +PROGRAM_OUTPUT="$programOutput" +DEFAULT_OS="$defaultOS" +DEFAULT_OS_ARCH="$defaultOSArch" +DEFAULT_WS="$defaultWS" +EXEC_DIR=../../../../../rt.equinox.binaries/org.eclipse.equinox.executable +OUTPUT_DIR="$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch" + +export OUTPUT_DIR PROGRAM_OUTPUT DEFAULT_OS DEFAULT_OS_ARCH DEFAULT_WS + +# If the OS is supported (a makefile exists) +if [ "$makefile" != "" ]; then + if [ "$extraArgs" != "" ]; then + make -f $makefile $extraArgs + else + echo "Building $OS launcher. Defaults: -os $DEFAULT_OS -arch $DEFAULT_OS_ARCH -ws $DEFAULT_WS" + make -f $makefile clean + make -f $makefile all + fi +else + echo "Unknown OS ($OS) -- build aborted" +fi diff --git a/features/org.eclipse.equinox.executable.feature/library/photon/build.xml b/features/org.eclipse.equinox.executable.feature/library/photon/build.xml new file mode 100644 index 000000000..990298e64 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/photon/build.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="install"/> + </exec> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="sh"> + <arg line="${basedir}/build.sh"/> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/photon/eclipsePhoton.c b/features/org.eclipse.equinox.executable.feature/library/photon/eclipsePhoton.c new file mode 100644 index 000000000..e5dfbd2a1 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/photon/eclipsePhoton.c @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + *******************************************************************************/ + +/* Photon specific logic for displaying the splash screen. */ + +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include <Pt.h> + +#define PX_IMAGE_MODULES +#define PX_BMP_SUPPORT + +#include <photon/PxImage.h> + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <libgen.h> + +/* Global Variables */ +char dirSeparator = '/'; +char pathSeparator = ':'; +#ifndef J9VM +char* defaultVM = "java"; +char* shippedVMDir = "jre/bin/"; +#else +char* defaultVM = "j9"; +char* shippedVMDir = "ive/bin/"; +#endif + +/* Define the window system arguments for the various Java VMs. */ +static char* argVM_JAVA[] = { NULL }; +static char* argVM_J9[] = { "-jit", "-ms:32", "-mso:256", NULL }; + + +/* Define local variables for the main window. */ +static PtWidget_t* topWindow = NULL; + +/* Define local variables for running the JVM and detecting its exit. */ +static pid_t jvmProcess = 0; +static int jvmExitCode; + +/* Local functions */ +static void bringDownSplashWindow( int ); +static void centreWindow( PtWidget_t *widget, PtWidget_t *label); +static int splashTimeout( PtWidget_t* widget, void* data, PtCallbackInfo_t* id ); + +/* Display a Message */ +void displayMessage( char* title, char* message ) +{ + if (topWindow == 0) + { + initWindowSystem( NULL, NULL, 0 ); + } + + PtNotice( NULL,NULL, title, NULL, message, NULL, NULL, NULL, Pt_CENTER | Pt_MODAL ); +} + + +/* Initialize Window System + * + * Initialize Photon. + */ +void initWindowSystem( int* pArgc, char* argv[], int showSplash ) +{ + PtArg_t arg[5]; + int nArgs; + + /* Create a top level window with no decorations. */ + setlocale(LC_ALL, ""); + PtInit( NULL ); + nArgs = 0; + PtSetArg( &arg[ nArgs++ ], Pt_ARG_WINDOW_RENDER_FLAGS, 0, ~0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_WINDOW_MANAGED_FLAGS, Ph_WM_TASKBAR | Ph_WM_CLOSE, ~0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_WINDOW_STATE, Ph_WM_STATE_ISFRONT, ~0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_WINDOW_TITLE, getOfficialName(), ~0 ); + topWindow = PtCreateWidget( PtWindow, Pt_NO_PARENT, nArgs, arg ); +} + + +/* Show the Splash Window + * + * Create the splash window, load the bitmap and display the splash window. + * + */ +int showSplash( char* timeoutString, char* featureImage ) +{ + int timeout = 0; + PtWidget_t* label; + PtArg_t arg[10]; + PhImage_t* image = NULL; + int nArgs; + int depth; + PgDisplaySettings_t settings; + PgVideoModeInfo_t mode_info; + + /* Determine the splash timeout value (in seconds). */ + if (timeoutString != NULL && strlen( timeoutString ) > 0) + { + sscanf( timeoutString, "%d", &timeout ); + } + + /* Install a signal handler to catch SIGUSR2 (which will shut down the window). */ + signal( SIGUSR2, bringDownSplashWindow ); + + /* Load the splash image from the feature directory. */ + PgGetVideoMode( &settings ); + PgGetVideoModeInfo( settings.mode, &mode_info ); + depth = mode_info.bits_per_pixel; + if (featureImage != NULL) + image = PxLoadImage( featureImage, NULL ); + + /* If the splash image could not be found, return an error. */ + if (image == NULL) + return ENOENT; + + /* Create a label widget (only child of top window) with the image. */ + nArgs = 0; + image->flags |= Ph_RELEASE_IMAGE_ALL; + PtSetArg( &arg[ nArgs++ ], Pt_ARG_LABEL_TYPE, Pt_IMAGE, 0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_LABEL_IMAGE, image, 0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_TEXT_STRING, officialName, 0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_MARGIN_WIDTH, 0, 0 ); + PtSetArg( &arg[ nArgs++ ], Pt_ARG_MARGIN_HEIGHT, 0, 0 ); + label = PtCreateWidget( PtLabel, topWindow, nArgs, arg ); + + /* Free the image */ + free( image ); + + /* Centre the splash window and display it. */ + centreWindow( topWindow, label ); + + /* If a timeout for the splash window was given */ + if (timeout != 0) + { + PtAddEventHandler( topWindow, Ph_EV_TIMER, splashTimeout, NULL ); + PtTimerArm( topWindow, (timeout * 1000) ); + } + + /* Process messages until the splash window is closed or process is terminated. */ + while (PtWidgetIsRealized( topWindow )) + { + PtProcessEvent(); + } + + /* Destroy the splash window. */ + PtDestroyWidget( topWindow ); + topWindow = 0; + + return 0; +} + + +/* Get the window system specific VM arguments */ +char** getArgVM( char* vm ) +{ + return (isJ9VM( vm ) ? argVM_J9 : argVM_JAVA); +} + +void fixEnvForJ9( char* vm ) { + if (isJ9VM( vm )) { + char *ldpath; + char newpath[PATH_MAX+1]; + + ldpath = getenv( "LD_LIBRARY_PATH" ); + + /* Always dup the string so we can free later */ + if( ldpath != NULL ) + ldpath = strdup( ldpath ); + else + ldpath = strdup( "" ); + + /* Get the j9 binary location */ + strncpy( newpath, vm, PATH_MAX ); + dirname( newpath ); + + /* Add j9 binary location to LD_LIBRARY_PATH */ + ldpath = realloc( ldpath, strlen( ldpath ) + strlen( newpath ) + 2 ); + if( ldpath != NULL ) + { + strcat( ldpath, ":" ); + strcat( ldpath, newpath ); + } + + setenv( "LD_LIBRARY_PATH", ldpath, 1 ); + + free( ldpath ); + } +} + +/* Start the Java VM + * + * This method is called to start the Java virtual machine and to wait until it + * terminates. The function returns the exit code from the JVM. + */ +int startJavaVM( char* args[] ) +{ + int exitCode; + + fixEnvForJ9 (args [0]); + + /* Create a child process for the JVM. */ + jvmProcess = fork(); + if (jvmProcess == 0) + { + /* Child process ... start the JVM */ + execv( args[0], args ); + + /* The JVM would not start ... return error code to parent process. */ + jvmExitCode = errno; + exit( jvmExitCode ); + } + + /* If the JVM is still running, wait for it to terminate. */ + if (jvmProcess != 0) + { + wait( &exitCode ); + jvmExitCode = ((exitCode & 0x00ff) == 0 ? (exitCode >> 8) : exitCode); /* see wait(2) */ + } + + /* Return the exit code from the JVM. */ + return jvmExitCode; +} + +/*------ Local functions -----*/ + + +/* Catch a signal that indicates the splash window is to be brought down. */ +static void bringDownSplashWindow( int sig ) +{ + if (topWindow != 0) + { + PtUnrealizeWidget( topWindow ); + } +} + + +/* Centre the top window on the screen. */ + +static void centreWindow( PtWidget_t* window, PtWidget_t* expose ) +{ + PtArg_t arg[2]; + int nArgs; + PhPoint_t pos; + PhArea_t area; + PhRect_t rect; + int width, height; + + /* Realize the top window to calculate its width/height. */ + PtExtentWidgetFamily( window ); + + /* Get the desired dimensions of the window. */ + PtWidgetArea( window, &area ); + + /* Calculate the X and Y position for the window. */ + PhWindowQueryVisible( Ph_QUERY_WORKSPACE, 0, PhInputGroup(0), &rect ); + width = rect.lr.x - rect.ul.x + 1; + height = rect.lr.y - rect.ul.y + 1; + pos.x = rect.ul.x + (width - area.size.w) / 2; + pos.y = rect.ul.y + (height - area.size.h) / 2; + + /* Set the new shell position and display it. */ + nArgs = 0; + PtSetArg( &arg[ nArgs++ ], Pt_ARG_POS, &pos, 0 ); + PtSetResources( window, nArgs, arg ); + PtRealizeWidget( window ); +} + + +/* Splash Timeout */ +static int splashTimeout( PtWidget_t* widget, void* data, PtCallbackInfo_t* info ) +{ + bringDownSplashWindow( 0 ); + return 1; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/photon/make_qnx.mak b/features/org.eclipse.equinox.executable.feature/library/photon/make_qnx.mak new file mode 100644 index 000000000..475cf48a3 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/photon/make_qnx.mak @@ -0,0 +1,57 @@ +#******************************************************************************* +# Copyright (c) 2000, 2006 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* + +# Makefile for creating the Photon eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch + +# Define the object modules to be compiled and flags. +OBJS = eclipse.o eclipseUtil.o eclipseShm.o eclipseConfig.o eclipsePhoton.o +EXEC = $(PROGRAM_OUTPUT) +LIBS = -lph -lphrender -lphexlib +CFLAGS = -O -s -Wall \ + -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -DJ9VM -I.. -DPHOTON + +all: $(EXEC) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +eclipse.o: ../eclipse.c ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipse.c -o $@ + +eclipseShm.o: ../eclipseShm.c ../eclipseShm.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseShm.c -o $@ + +eclipseConfig.o: ../eclipseConfig.c ../eclipseConfig.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseConfig.c -o $@ + +eclipseUtil.o: ../eclipseUtil.c ../eclipseUtil.h ../eclipseOS.h + $(CC) $(CFLAGS) -c ../eclipseUtil.c -o $@ + +$(EXEC): $(OBJS) + $(CC) -o $(EXEC) $(OBJS) $(LIBS) + +install: all + cp $(EXEC) $(OUTPUT_DIR) + rm -f $(EXEC) $(OBJS) + +clean: + rm -f $(EXEC) $(OBJS) diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/.cvsignore b/features/org.eclipse.equinox.executable.feature/library/win32/.cvsignore new file mode 100644 index 000000000..431170f6f --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/.cvsignore @@ -0,0 +1,8 @@ +*.obj +eclipse.exe +eclipse.res +*.pdb +*.exp +*.lib +eclipse_*.dll +eclipsec.exe diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/build.bat b/features/org.eclipse.equinox.executable.feature/library/win32/build.bat new file mode 100644 index 000000000..81f5afcd1 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/build.bat @@ -0,0 +1,156 @@ +@rem ******************************************************************************* +@rem Copyright (c) 2000, 2009 IBM Corporation and others. +@rem All rights reserved. This program and the accompanying materials +@rem are made available under the terms of the Eclipse Public License v1.0 +@rem which accompanies this distribution, and is available at +@rem http://www.eclipse.org/legal/epl-v10.html +@rem +@rem Contributors: +@rem IBM Corporation - initial API and implementation +@rem Kevin Cornell (Rational Software Corporation) +@rem ********************************************************************** +@rem +@rem Usage: sh build.sh [<optional switches>] [clean] +@rem +@rem where the optional switches are: +@rem -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +@rem -library <PROGRAM_LIBRARY>- dll filename (eclipse.dll) +@rem -os <DEFAULT_OS> - default Eclipse "-os" value (qnx) +@rem -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value (x86) +@rem -ws <DEFAULT_WS> - default Eclipse "-ws" value (photon) +@rem -java <JAVA_HOME> - location of a Java SDK for JNI headers +@rem +@rem +@rem This script can also be invoked with the "clean" argument. +@rem +@rem NOTE: The C compiler needs to be setup. This script has been +@rem tested against Microsoft Visual C and C++ Compiler 6.0. +@rem +@rem Uncomment the lines below and edit MSVC_HOME to point to the +@rem correct root directory of the compiler installation, if you +@rem want this to be done by this script. +@rem +@rem ****** +@echo off + +IF EXIST C:\BUILD\swt-builddir set LAUNCHER_BUILDDIR=C:\BUILD\swt-builddir +IF x.%LAUNCHER_BUILDDIR%==x. set LAUNCHER_BUILDDIR=S:\swt-builddir +echo LAUNCHER build dir: %LAUNCHER_BUILDDIR% + +IF x.%1==x.x86_64 GOTO X86_64 +IF x.%1==x.ia64 GOTO IA64 + +:X86 +IF x.%DEV_TOOLS%==x. set DEV_TOOLS=%LAUNCHER_BUILDDIR% +IF x.%JAVA_HOME%==x. set JAVA_HOME=%LAUNCHER_BUILDDIR%\ibm-java2-sdk-50-win-i386 +set javaHome=%JAVA_HOME% +if not x.%MSVC_HOME% == x. goto MAKE +set MSVC_HOME="%LAUNCHER_BUILDDIR%\MSVCs\msvc60\VC98" +call %MSVC_HOME%\bin\vcvars32.bat +if not "%MSSDK%" == "" goto MAKE +set MSSDK="%LAUNCHER_BUILDDIR%\MSSDKs\feb2003" +call %MSSDK%\setenv.bat +IF x.%1==x.x86 shift +set defaultOSArch=x86 +set makefile=make_win32.mak +GOTO MAKE + +:X86_64 +shift +set defaultOSArch=x86_64 +IF x.%JAVA_HOME%==x. set JAVA_HOME=%LAUNCHER_BUILDDIR%\ibm-sdk50-x86_64 +IF "x.%MSSDK%" == "x." set MSSDK="%LAUNCHER_BUILDDIR%\MSSDKs\Windows Server 2003 SP1 SDK" +set javaHome=%JAVA_HOME% +set makefile=make_win64.mak +call %MSSDK%\setenv /X64 /RETAIL +GOTO MAKE + +:IA64 +shift +set defaultOSArch=ia64 +IF x.%JAVA_HOME%==x. set JAVA_HOME=%LAUNCHER_BUILDDIR%\ibm-sdk142-ia64 +IF "x.%MSSDK%" == "x." set MSSDK="%LAUNCHER_BUILDDIR%\MSSDKs\Windows Server 2003 SP1 SDK" +set javaHome=%JAVA_HOME% +set makefile=make_win64_ia64.mak +call %MSSDK%\setenv /SRV64 /RETAIL +GOTO MAKE + +:MAKE +rem -------------------------- +rem Define default values for environment variables used in the makefiles. +rem -------------------------- +set programOutput=eclipse.exe +set programLibrary=eclipse.dll +set defaultOS=win32 +set defaultWS=win32 +set OS=Windows + +rem -------------------------- +rem Parse the command line arguments and override the default values. +rem -------------------------- +set extraArgs= +:WHILE +if "%1" == "" goto WHILE_END + if "%2" == "" goto LAST_ARG + + if "%1" == "-os" ( + set defaultOS=%2 + shift + goto NEXT ) + if "%1" == "-arch" ( + set defaultOSArch=%2 + shift + goto NEXT ) + if "%1" == "-ws" ( + set defaultWS=%2 + shift + goto NEXT ) + if "%1" == "-output" ( + set programOutput=%2 + shift + goto NEXT ) + if "%1" == "-library" ( + set programLibrary=%2 + shift + goto NEXT ) + if "%1" == "-java" ( + set javaHome=%2 + echo %javaHome% + shift + goto NEXT ) +:LAST_ARG + set extraArgs=%extraArgs% %1 + +:NEXT + shift + goto WHILE +:WHILE_END + +rem -------------------------- +rem Set up environment variables needed by the makefile. +rem -------------------------- +set PROGRAM_OUTPUT=%programOutput% +set PROGRAM_LIBRARY=%programLibrary% +set DEFAULT_OS=%defaultOS% +set DEFAULT_OS_ARCH=%defaultOSArch% +set DEFAULT_WS=%defaultWS% +set EXEC_DIR=..\..\.\..\..\rt.equinox.binaries\org.eclipse.equinox.executable +set OUTPUT_DIR=%EXEC_DIR%\bin\%defaultWS%\%defaultOS%\%defaultOSArch% +set JAVA_HOME=%javaHome% + +rem -------------------------- +rem Run nmake to build the executable. +rem -------------------------- +if "%extraArgs%" == "" goto MAKE_ALL + +nmake -f %makefile% %extraArgs% +goto DONE + +:MAKE_ALL +echo Building %OS% launcher. Defaults: -os %DEFAULT_OS% -arch %DEFAULT_OS_ARCH% -ws %DEFAULT_WS% +nmake -f %makefile% clean +nmake -f %makefile% %1 %2 %3 %4 +goto DONE + + +:DONE diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/build.sh b/features/org.eclipse.equinox.executable.feature/library/win32/build.sh new file mode 100644 index 000000000..853eaf4cf --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/build.sh @@ -0,0 +1,77 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2000, 2006 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* +# +# Usage: sh build.sh [<optional switches>] [clean] +# +# where the optional switches are: +# -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +# -os <DEFAULT_OS> - default Eclipse "-os" value +# -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value +# -ws <DEFAULT_WS> - default Eclipse "-ws" value +# +# +# This script can also be invoked with the "clean" argument. + +cd `dirname $0` + +# Define default values for environment variables used in the makefiles. +programOutput="eclipse.exe" +defaultOS="win32" +defaultOSArch="x86" +defaultWS="win32" +makefile="make_mingw.mak" +OS="Windows" + +# Parse the command line arguments and override the default values. +extraArgs="" +while [ "$1" != "" ]; do + if [ "$1" = "-os" ] && [ "$2" != "" ]; then + defaultOS="$2" + shift + elif [ "$1" = "-arch" ] && [ "$2" != "" ]; then + defaultOSArch="$2" + shift + elif [ "$1" = "-ws" ] && [ "$2" != "" ]; then + defaultWS="$2" + shift + elif [ "$1" = "-output" ] && [ "$2" != "" ]; then + programOutput="$2" + shift + else + extraArgs="$extraArgs $1" + fi + shift +done + +# Set up environment variables needed by the makefiles. +PROGRAM_OUTPUT="$programOutput" +DEFAULT_OS="$defaultOS" +DEFAULT_OS_ARCH="$defaultOSArch" +DEFAULT_WS="$defaultWS" +EXEC_DIR=../../../../../rt.equinox.binaries/org.eclipse.equinox.executable +OUTPUT_DIR=$EXEC_DIR/bin/$defaultWS/$defaultOS/$defaultOSArch + +export OUTPUT_DIR PROGRAM_OUTPUT DEFAULT_OS DEFAULT_OS_ARCH DEFAULT_WS + +# If the OS is supported (a makefile exists) +if [ "$makefile" != "" ]; then + if [ "$extraArgs" != "" ]; then + make -f $makefile $extraArgs + else + echo "Building $OS launcher. Defaults: -os $DEFAULT_OS -arch $DEFAULT_OS_ARCH -ws $DEFAULT_WS" + make -f $makefile clean + make -f $makefile all + fi +else + echo "Unknown OS ($OS) -- build aborted" +fi diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/build.xml b/features/org.eclipse.equinox.executable.feature/library/win32/build.xml new file mode 100644 index 000000000..056b85926 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/build.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="${basedir}\build.bat"> + <arg line="install"/> + </exec> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="${basedir}\build.bat"> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.exe.manifest b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.exe.manifest new file mode 100644 index 000000000..dda153470 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.exe.manifest @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="3.1.0.0" processorArchitecture="*" name="Eclipse Launcher" type="win32"/> + <description>Standard Widget Toolkit</description> + <dependency> + <dependentAssembly> + <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> + </dependentAssembly> + </dependency> +</assembly> +
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.ico b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.ico Binary files differnew file mode 100644 index 000000000..d73e6869c --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.ico diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.rc b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.rc new file mode 100644 index 000000000..c05708362 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/eclipse.rc @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#define ECLIPSE_ICON 401 + +#include "windows.h" +#include "winver.h" + + +ECLIPSE_ICON ICON DISCARDABLE "eclipse.ico" + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "eclipse.exe.manifest" + diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWin.c b/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWin.c new file mode 100644 index 000000000..387576994 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWin.c @@ -0,0 +1,619 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + *******************************************************************************/ + +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include "eclipseCommon.h" +#include "eclipseJNI.h" +#include "eclipseShm.h" + +#include <windows.h> +#include <commctrl.h> +#include <process.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +#ifdef __MINGW32__ +#include <stdlib.h> +#endif + +extern HWND topWindow; + +/* Global Variables */ +_TCHAR* defaultVM = _T("javaw.exe"); +_TCHAR* consoleVM = _T("java.exe"); +_TCHAR* vmLibrary = _T("jvm.dll"); +_TCHAR* shippedVMDir = _T("jre\\bin\\"); + +/* Define local variables for communicating with running eclipse instance. */ +static HANDLE mutex; +static UINT findWindowTimeout = 1000; +static UINT_PTR findWindowTimerId = 97; +static UINT timerCount = 0; +static UINT openFileTimeout = 60; +static _TCHAR** openFilePath; + +/* Define the window system arguments for the Java VM. */ +static _TCHAR* argVM[] = { NULL }; + +/* Define local variables for running the JVM and detecting its exit. */ +static HANDLE jvmProcess = 0; +static JavaResults* jvmResults = NULL; +static UINT jvmExitTimeout = 100; +static UINT_PTR jvmExitTimerId = 99; + +static void CALLBACK findWindowProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime); +static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime ); +static _TCHAR* checkVMRegistryKey(HKEY jrekey, _TCHAR* subKeyName); +static void adjustSearchPath( _TCHAR * vmLibrary ); +static _TCHAR* findLib( _TCHAR* command ); + +/* define default locations in which to find the jvm shared library + * these are paths relative to the java exe, the shared library is + * for example jvmLocations[0] + dirSeparator + vmLibrary */ +#define MAX_LOCATION_LENGTH 25 /* none of the jvmLocations strings should be longer than this */ +static const _TCHAR* jvmLocations [] = { _T("j9vm"), _T("..\\jre\\bin\\j9vm"), + _T("client"), _T("..\\jre\\bin\\client"), + _T("server"), _T("..\\jre\\bin\\server"), + _T("classic"), _T("..\\jre\\bin\\classic"), + _T("jrockit"), _T("..\\jre\\bin\\jrockit"), + NULL }; + +/* for detecting sun vms */ +typedef struct { + WORD language; + WORD codepage; +} TRANSLATIONS; + +#define COMPANY_NAME_KEY _T_ECLIPSE("\\StringFileInfo\\%04x%04x\\CompanyName") +#define SUN_MICROSYSTEMS _T_ECLIPSE("Sun Microsystems") +#define ORACLE _T_ECLIPSE("Oracle") + +static void sendOpenFileMessage(HWND window) { + _TCHAR* id; + UINT msg; + int index = 0; + int size = 0; + DWORD wParam; +#ifdef WIN64 + DWORDLONG lParam; +#else + DWORD lParam; +#endif + + /* what's the longest path? */ + while (openFilePath[index] != NULL) { + int length = _tcslen(openFilePath[index++]); + if (size <= length) + size = length + 1; + } + + createSharedData(&id, size * sizeof(_TCHAR)); + _stscanf(id, _T_ECLIPSE("%lx_%lx"), &wParam, &lParam); + msg = RegisterWindowMessage(_T("SWT_OPENDOC")); + + index = 0; + for(index = 0; openFilePath[index] != NULL; index++) { + /* SendMessage does not return until the message has been processed */ + setSharedData(id, openFilePath[index]); + SendMessage(window, msg, wParam, lParam); + } + destroySharedData(id); + free(id); +} + +static HWND findSWTMessageWindow() { + HWND window = NULL; + _TCHAR *windowTitle, *windowPrefix, *name; + + windowPrefix = _T("SWT_Window_"); + name = getOfficialName(); + windowTitle = malloc((_tcslen(windowPrefix) + _tcslen(name) + 1) * sizeof(_TCHAR)); + _stprintf(windowTitle, _T_ECLIPSE("%s%s"), windowPrefix, name); + window = FindWindow(NULL, windowTitle); + free(windowTitle); + return window; +} + +static void CALLBACK findWindowProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime) { + HWND window = findSWTMessageWindow(); + if (window != NULL) { + sendOpenFileMessage(window); + ReleaseMutex(mutex); + CloseHandle(mutex); + KillTimer(hwnd, findWindowTimerId); + return; + } + + /* no window yet, set timer to try again later */ + if (timerCount++ >= openFileTimeout) { + KillTimer(hwnd, findWindowTimerId); + ReleaseMutex(mutex); + CloseHandle(mutex); + } +} + +/* return > 0 if we successfully send a message to another eclipse instance */ +int reuseWorkbench(_TCHAR** filePath, int timeout) { + _TCHAR* mutexPrefix = _T("SWT_Mutex_"); + _TCHAR* mutexName, *name; + DWORD lock; + HWND window = NULL; + + /* store for later */ + openFilePath = filePath; + openFileTimeout = timeout; + + name = getOfficialName(); + mutexName = malloc((_tcslen(mutexPrefix) + _tcslen(name) + 1) * sizeof(_TCHAR)); + _stprintf(mutexName, _T_ECLIPSE("%s%s"), mutexPrefix, name); + mutex = CreateMutex(NULL, FALSE, mutexName); + free(mutexName); + if (mutex == NULL) return -1; + + //wait for timeout seconds + lock = WaitForSingleObject(mutex, timeout * 1000); + if (lock != WAIT_OBJECT_0) { + /* failed to get the lock before timeout, We won't be reusing an existing eclipse. */ + CloseHandle(mutex); + return 0; + } + + /* we have the mutex, look for the SWT window */ + window = findSWTMessageWindow(); + if (window != NULL) { + sendOpenFileMessage(window); + ReleaseMutex(mutex); + CloseHandle(mutex); + return 1; /* success! */ + } + + /* no window, set a timer to look again later */ + if (initWindowSystem(0, NULL, 0) == 0) + SetTimer( topWindow, findWindowTimerId, findWindowTimeout, findWindowProc ); + + return 0; +} + +/* Show the Splash Window + * + * Open the bitmap, insert into the splash window and display it. + * + */ +int showSplash( const _TCHAR* featureImage ) +{ + static int splashing = 0; + HBITMAP hBitmap = 0; + BITMAP bmp; + HDC hDC; + int depth; + int x, y; + int width, height; + + if(splashing) { + /*splash screen is already showing, do nothing */ + return 0; + } + if (featureImage == NULL) + return -1; + + /* if Java was started first and is calling back to show the splash, we might not + * have initialized the window system yet + */ + initWindowSystem(0, NULL, 1); + + /* Load the bitmap for the feature. */ + hDC = GetDC( NULL); + depth = GetDeviceCaps( hDC, BITSPIXEL ) * GetDeviceCaps( hDC, PLANES); + ReleaseDC(NULL, hDC); + if (featureImage != NULL) + hBitmap = LoadImage(NULL, featureImage, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + + /* If the bitmap could not be found, return an error. */ + if (hBitmap == 0) + return ERROR_FILE_NOT_FOUND; + + GetObject(hBitmap, sizeof(BITMAP), &bmp); + + /* figure out position */ + width = GetSystemMetrics (SM_CXSCREEN); + height = GetSystemMetrics (SM_CYSCREEN); + x = (width - bmp.bmWidth) / 2; + y = (height - bmp.bmHeight) / 2; + + /* Centre the splash window and display it. */ + SetWindowPos (topWindow, 0, x, y, bmp.bmWidth, bmp.bmHeight, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + SendMessage( topWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBitmap ); + ShowWindow( topWindow, SW_SHOW ); + BringWindowToTop( topWindow ); + splashing = 1; + + /* Process messages */ + dispatchMessages(); + return 0; +} + +void dispatchMessages() { + MSG msg; + + if(topWindow == 0) + return; + while (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +} + +jlong getSplashHandle() { + return (jlong)topWindow; +} + +void takeDownSplash() { + if(topWindow != NULL) { + DestroyWindow(topWindow); + dispatchMessages(); + topWindow = 0; + } +} + +/* Get the window system specific VM args */ +_TCHAR** getArgVM( _TCHAR *vm ) +{ + return argVM; +} + +/* Local functions */ + +_TCHAR * findVMLibrary( _TCHAR* command ) { + _TCHAR* lib = findLib(command); + if( lib != NULL ) { + adjustSearchPath(lib); + } + return lib; +} + +void adjustSearchPath( _TCHAR* vmLib ){ + _TCHAR ** paths; + _TCHAR* cwd = NULL; + _TCHAR * path = NULL, *newPath = NULL; + _TCHAR * c; + int i, length; + int needAdjust = 0, freePath = 0; + + paths = getVMLibrarySearchPath(vmLib); + + /* bug 325902 - add current working dir to the end of the search path */ + length = GetCurrentDirectory(0, NULL); + cwd = malloc((length + 1)* sizeof(_TCHAR)); + GetCurrentDirectory(length, cwd); + cwd[length - 1] = pathSeparator; + cwd[length] = 0; + + /* first call to GetEnvironmentVariable tells us how big to make the buffer */ + length = GetEnvironmentVariable(_T_ECLIPSE("PATH"), path, 0); + if (length > 0) { + _TCHAR* current [] = { cwd, NULL }; + path = malloc(length * sizeof(_TCHAR)); + GetEnvironmentVariable(_T_ECLIPSE("PATH"), path, length); + needAdjust = !containsPaths(path, paths) || !containsPaths(path, current); + freePath = 1; + } else { + path = _T_ECLIPSE(""); + freePath = 0; + needAdjust = 1; + } + + if (needAdjust) { + c = concatStrings(paths); + newPath = malloc((_tcslen(c) + length + 1 + _tcslen(cwd) + 1) * sizeof(_TCHAR)); + _stprintf(newPath, _T_ECLIPSE("%s%s%c%s"), c, path, pathSeparator, cwd); + SetEnvironmentVariable( _T_ECLIPSE("PATH"), newPath); + free(c); + free(newPath); + } + + for (i = 0; paths[i] != NULL; i++) + free(paths[i]); + free(paths); + free(cwd); + if (freePath) + free(path); +} +/* + * Find the VM shared library starting from the java executable + */ +static _TCHAR* findLib( _TCHAR* command ) { + int i, j; + size_t pathLength; + struct _stat stats; + _TCHAR * path; /* path to resulting jvm shared library */ + _TCHAR * location; /* points to begining of jvmLocations section of path */ + + /* for looking in the registry */ + HKEY jreKey = NULL; + DWORD length = MAX_PATH; + _TCHAR keyName[MAX_PATH]; + _TCHAR * jreKeyName; + + if (command != NULL) { + location = lastDirSeparator( command ) + 1; + + /*check first to see if command already points to the library */ + if (isVMLibrary(command)) { + if (_tstat( command, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + return command; /* exists */ + return NULL; /* doesn't exist */ + } + + pathLength = (size_t) (location - command); + path = malloc((pathLength + MAX_LOCATION_LENGTH + 1 + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); + _tcsncpy(path, command, pathLength); + location = &path[pathLength]; + + /* + * We are trying base/jvmLocations[*]/vmLibrary + * where base is the directory containing the given java command, normally jre/bin + */ + i = -1; + while(jvmLocations[++i] != NULL) { + _stprintf(location, _T_ECLIPSE("%s%c%s"), jvmLocations[i], dirSeparator, vmLibrary); + if (_tstat( path, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /* found it */ + return path; + } + } + + /* if command is eclipse/jre, don't look in registry */ + location = malloc( (_tcslen( getProgramDir() ) + _tcslen( shippedVMDir ) + 1) * sizeof(_TCHAR) ); + _stprintf( location, _T_ECLIPSE("%s%s"), getProgramDir(), shippedVMDir ); + if( _tcsncmp(command, location, _tcslen(location)) == 0) { + free(location); + return NULL; + } + free(location); + } + + /* Not found yet, try the registry, we will use the first vm >= 1.4 */ + jreKeyName = _T("Software\\JavaSoft\\Java Runtime Environment"); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, jreKeyName, 0, KEY_READ, &jreKey) == ERROR_SUCCESS) { + if(RegQueryValueEx(jreKey, _T_ECLIPSE("CurrentVersion"), NULL, NULL, (void*)&keyName, &length) == ERROR_SUCCESS) { + path = checkVMRegistryKey(jreKey, keyName); + if (path != NULL) { + RegCloseKey(jreKey); + return path; + } + } + j = 0; + length = MAX_PATH; + while (RegEnumKeyEx(jreKey, j++, keyName, &length, 0, 0, 0, 0) == ERROR_SUCCESS) { + /*look for a 1.4 or 1.5 vm*/ + if( _tcsncmp(_T("1.4"), keyName, 3) <= 0 ) { + path = checkVMRegistryKey(jreKey, keyName); + if (path != NULL) { + RegCloseKey(jreKey); + return path; + } + } + } + RegCloseKey(jreKey); + } + return NULL; +} + +/* + * Read the subKeyName subKey of jreKey and look to see if it has a Value + * "RuntimeLib" which points to a jvm library we can use + * + * Does not close jreKey + */ +static _TCHAR* checkVMRegistryKey(HKEY jreKey, _TCHAR* subKeyName) { + _TCHAR value[MAX_PATH]; + HKEY subKey = NULL; + DWORD length = MAX_PATH; + _TCHAR *result = NULL; + struct _stat stats; + + if(RegOpenKeyEx(jreKey, subKeyName, 0, KEY_READ, &subKey) == ERROR_SUCCESS) { + /*The RuntimeLib value should point to the library we want*/ + if(RegQueryValueEx(subKey, _T("RuntimeLib"), NULL, NULL, (void*)&value, &length) == ERROR_SUCCESS) { + if (_tstat( value, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /*library exists*/ + result = _tcsdup(value); + } + } + RegCloseKey(subKey); + } + return result; +} + +static _TCHAR* buildCommandLine( _TCHAR* program, _TCHAR* args[] ) +{ + int index, slash; + size_t length = 0; + _TCHAR *commandLine, *ch, *space; + + /* + * Build the command line. Any argument with spaces must be in + * double quotes in the command line. + */ + if(program != NULL) + length = _tcslen(program) + 1; + for (index = 0; args[index] != NULL; index++) + { + /* String length plus space character */ + length += _tcslen( args[ index ] ) + 1; + /* Quotes + potential escaping '\' */ + if (_tcschr( args[ index ], _T(' ') ) != NULL) length += 3; + } + + commandLine = ch = malloc ( (length + 1) * sizeof(_TCHAR) ); + if (program != NULL) { + _tcscpy(ch, program); + ch += _tcslen(program); + *ch++ = _T(' '); + } + for (index = 0; args[index] != NULL; index++) + { + space = _tcschr( args[ index ], _T(' ')); + if (space != NULL) *ch++ = _T('\"'); + _tcscpy( ch, args[index] ); + ch += _tcslen( args[index] ); + if (space != NULL) { + if ( *(ch - 1) == _T('\\') ) { + /* escape a trailing unescaped '\' or it will escape our closing '"' and mess things up */ + slash = 1; + while ( *(ch - 1 - slash) == _T('\\')) slash++; + if (slash % 2) *ch++ = _T('\\'); + } + *ch++ = _T('\"'); + } + *ch++ = _T(' '); + } + *ch = _T('\0'); + return commandLine; +} +void restartLauncher( _TCHAR* program, _TCHAR* args[] ) +{ + _TCHAR* commandLine = buildCommandLine(program, args); + + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + GetStartupInfo(&si); + if (CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle( pi.hThread ); + } + } + free(commandLine); +} + +JavaResults* launchJavaVM( _TCHAR* args[] ) +{ + MSG msg; + _TCHAR* commandLine; + jvmProcess = 0; + commandLine = buildCommandLine(NULL, args); + jvmResults = malloc(sizeof(JavaResults)); + memset(jvmResults, 0, sizeof(JavaResults)); + + /* + * Start the Java virtual machine. Use CreateProcess() instead of spawnv() + * otherwise the arguments cannot be freed since spawnv() segments fault. + */ + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + GetStartupInfo(&si); + if (CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle( pi.hThread ); + jvmProcess = pi.hProcess; + } else { + jvmResults->launchResult = errno; + } + } + + free( commandLine ); + + if (jvmProcess > 0) + { + /* Set a timer to detect JVM process termination. */ + SetTimer( topWindow, jvmExitTimerId, jvmExitTimeout, detectJvmExit ); + + /* Process messages until the JVM terminates. + This launcher process must continue to process events until the JVM exits + or else Windows 2K will hang if the desktop properties (e.g., background) are + changed by the user. Windows does a SendMessage() to every top level window + process, which blocks the caller until the process responds. */ + while (jvmProcess != 0) + { + GetMessage( &msg, NULL, 0, 0 ); + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + + /* Kill the timer. */ + KillTimer( topWindow, jvmExitTimerId ); + } + + /* Return the exit code from the JVM. */ + return jvmResults; +} + +/* Detect JVM Process Termination */ +static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime ) +{ + DWORD exitCode; + + /* If the JVM process has terminated */ + if (!GetExitCodeProcess( (HANDLE)jvmProcess, &exitCode ) || + exitCode != STILL_ACTIVE) + { + /* Save the JVM exit code. This should cause the loop in launchJavaVM() to exit. */ + jvmResults->runResult = exitCode; + jvmProcess = 0; + } +} + +void processVMArgs(_TCHAR **vmargs[] ) { + /* nothing yet */ +} + +JavaResults* startJavaVM( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ) +{ + return startJavaJNI(libPath, vmArgs, progArgs, jarFile); +} + +int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ) { + _TCHAR *vm = (jniLib != NULL) ? jniLib : javaVM; + int result = 0; + DWORD infoSize; + DWORD handle; + void * info; + + _TCHAR * key, *value; + size_t i; + int valueSize; + + if (vm == NULL) + return 0; + + infoSize = GetFileVersionInfoSize(vm, &handle); + if (infoSize > 0) { + info = malloc(infoSize); + if (GetFileVersionInfo(vm, 0, infoSize, info)) { + TRANSLATIONS * translations; + int translationsSize; + VerQueryValue(info, _T_ECLIPSE("\\VarFileInfo\\Translation"), (void *) &translations, &translationsSize); + + /* this size is only right because %04x is 4 characters */ + key = malloc( (_tcslen(COMPANY_NAME_KEY) + 1) * sizeof(_TCHAR)); + for (i = 0; i < (translationsSize / sizeof(TRANSLATIONS)); i++) { + _stprintf(key, COMPANY_NAME_KEY, translations[i].language, translations[i].codepage); + + VerQueryValue(info, key, (void *)&value, &valueSize); + if (_tcsncmp(value, SUN_MICROSYSTEMS, _tcslen(SUN_MICROSYSTEMS)) == 0) { + result = 1; + break; + } else if (_tcsncmp(value, ORACLE, _tcslen(ORACLE)) == 0) { + result = 1; + break; + } + } + free(key); + } + free(info); + } + return result; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWinCommon.c b/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWinCommon.c new file mode 100644 index 000000000..27546bfaa --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/eclipseWinCommon.c @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + +#include "eclipseCommon.h" +#include "eclipseOS.h" + +#include <windows.h> +#include <stdlib.h> +#include <commctrl.h> + +#define ECLIPSE_ICON 401 + +_TCHAR dirSeparator = _T('\\'); +_TCHAR pathSeparator = _T(';'); + +/* Global Main Window*/ +HWND topWindow = 0; + +/* Define local variables for the main window. */ +/*static WNDPROC oldProc;*/ + +static int initialized = 0; + +/* Display a Message */ +void displayMessage( _TCHAR* title, _TCHAR* message ) +{ + if(!initialized) + initWindowSystem(0, NULL, 0); + MessageBox( topWindow, message, title, MB_OK ); +} + +/* Initialize Window System + * + * Create a pop window to display the bitmap image. + * + * Return the window handle as the data for the splash command. + * + */ +int initWindowSystem( int* pArgc, _TCHAR* argv[], int showSplash ) +{ + HINSTANCE module = GetModuleHandle(NULL); + HICON icon = NULL; + + if(initialized) + return 0; + + icon = LoadIcon(module, MAKEINTRESOURCE(ECLIPSE_ICON)); + if (icon == NULL) { + HMODULE hm = LoadLibraryEx(getProgramPath(), 0, LOAD_LIBRARY_AS_DATAFILE & 0x2 /*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/); + if (hm != NULL) + icon = LoadIcon(hm, MAKEINTRESOURCE(ECLIPSE_ICON)); + } + + /* Create a window that has no decorations. */ + InitCommonControls(); + topWindow = CreateWindowEx ( icon != NULL ? 0 : WS_EX_TOOLWINDOW, + _T("STATIC"), + getOfficialName(), + SS_BITMAP | WS_POPUP | WS_CLIPCHILDREN, + CW_USEDEFAULT, + 0, + CW_USEDEFAULT, + 0, + NULL, + NULL, + module, + NULL); + + if (icon != NULL) +#ifdef WIN64 + SetClassLongPtr(topWindow, GCLP_HICON, (LONG_PTR)icon); +#else + SetClassLong(topWindow, GCL_HICON, (LONG)icon); +#endif + + initialized = 1; + return 0; +} + +/* Load the specified shared library + */ +void * loadLibrary( _TCHAR * library ){ + return LoadLibrary(library); +} + +/* Unload the shared library + */ +void unloadLibrary( void * handle ){ + FreeLibrary(handle); +} + +/* Find the given symbol in the shared library + */ +void * findSymbol( void * handle, _TCHAR * symbol ){ + char * str = NULL; + void * result; + + str = toNarrow(symbol); + result = GetProcAddress(handle, str); + free(str); + return result; +} + +_TCHAR* resolveSymlinks( _TCHAR* path ) { + /* no symlinks on windows */ + return path; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/make_mingw.mak b/features/org.eclipse.equinox.executable.feature/library/win32/make_mingw.mak new file mode 100644 index 000000000..aaee41e85 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/make_mingw.mak @@ -0,0 +1,127 @@ +#******************************************************************************* +# Copyright (c) 2000, 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +# Silenio Quarti (IBM) +# Sam Robb (TimeSys Corporation) +#******************************************************************************* +include ../make_version.mak +# Makefile for creating the eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the file of the output shared library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch + +#if PROGRAM_OUTPUT is not set, assume eclipse.exe +ifeq ($(PROGRAM_OUTPUT),) + PROGRAM_OUTPUT=eclipse.exe +endif + +# Separate filename from extention +PROGRAM_NAME=$(PROGRAM_OUTPUT:.exe=) + +PROGRAM_LIBRARY=eclipse_$(LIB_VERSION).dll + +# Allow for cross-compiling under linux +OSTYPE ?= $(shell if uname -s | grep -iq cygwin ; then echo cygwin; else echo linux; fi) + +ifeq ($(OSTYPE),cygwin) +CCVER = i686 +CC = i686-pc-cygwin-gcc-3 +RC = windres +else +CCVER = i586 +CC = $(shell which i586-pc-cygwin-gcc) +TDIR = $(dir $(shell test -L $(CC) && readlink $(CC) || echo $(CC))) +RC = $(TDIR)/i586-pc-cygwin-windres +SYSINC = -isystem $(TDIR)/../include/mingw +endif + +ifeq ($(CC),) +$(error Unable to find $(CCVER)-pc-cygwin-gcc) +endif + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.o +COMMON_OBJS = eclipseConfig.o eclipseCommon.o eclipseWinCommon.o +DLL_OBJS = eclipse.o eclipseWin.o eclipseUtil.o eclipseJNI.o eclipseShm.o + +LIBS = -lkernel32 -luser32 -lgdi32 -lcomctl32 -lmsvcrt -lversion +LDFLAGS = -mwindows -mno-cygwin +CONSOLEFLAGS = -mconsole -mno-cygwin +DLL_LDFLAGS = -mno-cygwin -shared -Wl,--export-all-symbols -Wl,--kill-at,--image-base=0x72000000 +RES = $(PROGRAM_NAME).res +CONSOLE = $(PROGRAM_NAME)c.exe +EXEC = $(PROGRAM_OUTPUT) +DLL = $(PROGRAM_LIBRARY) +DEBUG = $(CDEBUG) +CFLAGS = -g -s -Wall \ + -I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 $(SYSINC) \ + -D_WIN32 \ + -DWIN32_LEAN_AND_MEAN \ + -mno-cygwin -D__int64="long long" +WCFLAGS = -DUNICODE -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + $(DEBUG) $(CFLAGS) + +all: $(EXEC) $(DLL) $(CONSOLE) + +eclipseMain.o: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseMain.c + +eclipseCommon.o: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseCommon.c + +eclipseWinCommon.o: ../eclipseCommon.h eclipseWinCommon.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ eclipseWinCommon.c + +eclipse.o: ../eclipseOS.h ../eclipseUnicode.h ../eclipseJNI.h ../eclipseCommon.h ../eclipse.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipse.c + +eclipseUtil.o: ../eclipseUtil.h ../eclipseUnicode.h ../eclipseUtil.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseUtil.c + +eclipseConfig.o: ../eclipseConfig.h ../eclipseUnicode.h ../eclipseConfig.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseConfig.c + +eclipseWin.o: ../eclipseOS.h ../eclipseUnicode.h eclipseWin.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ eclipseWin.c + +eclipseJNI.o: ../eclipseUnicode.h ../eclipseJNI.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseJNI.c + +eclipseShm.o: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(DEBUG) $(WCFLAGS) -c -o $@ ../eclipseShm.c + +$(RES): $(PROGRAM_NAME).rc + $(RC) --output-format=coff --include-dir=.. -o $@ $< + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) $(RES) + $(CC) $(LDFLAGS) -o $(EXEC) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) + +#the console version needs a flag set, should look for a better way to do this +$(CONSOLE): $(MAIN_OBJS) $(COMMON_OBJS) + rm -f eclipseConfig.o aeclipseConfig.o + $(CC) $(DEBUG) $(WCFLAGS) -D_WIN32_CONSOLE -c -o eclipseConfig.o ../eclipseConfig.c + $(CC) $(CONSOLEFLAGS) -o $(CONSOLE) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(CC) $(DLL_LDFLAGS) -o $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(LIBS) + +install: all + cp $(EXEC) $(DLL) $(CONSOLE) $(OUTPUT_DIR) + rm -f $(EXEC) $(DLL_OBJS) $(COMMON_OBJS) $(MAIN_OBJS) $(RES) $(CONSOLE) + +clean: + $(RM) $(EXEC) $(DLL) $(DLL_OBJS) $(COMMON_OBJS) $(MAIN_OBJS) $(RES) $(CONSOLE) diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/make_win32.mak b/features/org.eclipse.equinox.executable.feature/library/win32/make_win32.mak new file mode 100644 index 000000000..252708832 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/make_win32.mak @@ -0,0 +1,103 @@ +#****************************************************************************** +# Copyright (c) 2000, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* + +# Makefile for creating the eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output dll library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - the location of the Java for JNI includes +NODEBUG=1 +!include <ntwin32.mak> +!include <..\make_version.mak> + +PROGRAM_OUTPUT=eclipse.exe +# Separate filename from extention +PROGRAM_NAME=$(PROGRAM_OUTPUT:.exe=) + +PROGRAM_LIBRARY = eclipse_$(LIB_VERSION).dll + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.obj +COMMON_OBJS = eclipseConfig.obj eclipseCommon.obj eclipseWinCommon.obj +DLL_OBJS = eclipse.obj eclipseWin.obj eclipseUtil.obj eclipseJNI.obj eclipseShm.obj + +LIBS = kernel32.lib user32.lib comctl32.lib msvcrt.lib +DLL_LIBS = kernel32.lib user32.lib comctl32.lib gdi32.lib Advapi32.lib msvcrt.lib version.lib +LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /LARGEADDRESSAWARE /RELEASE /NOLOGO -subsystem:windows,4.0 -entry:wmainCRTStartup +CONSOLEFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /LARGEADDRESSAWARE /RELEASE /NOLOGO -subsystem:console,4.0 -entry:wmainCRTStartup +DLL_LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /LARGEADDRESSAWARE /PDB:NONE /RELEASE /NOLOGO -entry:_DllMainCRTStartup@12 -dll /BASE:0x72000000 /DLL +RES = $(PROGRAM_NAME).res +EXEC = $(PROGRAM_OUTPUT) +CONSOLE = $(PROGRAM_NAME)c.exe +DLL = $(PROGRAM_LIBRARY) +DEBUG = #$(cdebug) +wcflags = -DUNICODE -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 \ + $(cflags) + +all: $(EXEC) $(DLL) $(CONSOLE) + +eclipseMain.obj: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseMain.c + +eclipseCommon.obj: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseCommon.c + +eclipse.obj: ../eclipseOS.h ../eclipseUnicode.h ../eclipse.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipse.c + +eclipseUtil.obj: ../eclipseUtil.h ../eclipseUnicode.h ../eclipseUtil.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseUtil.c + +eclipseConfig.obj: ../eclipseConfig.h ../eclipseUnicode.h ../eclipseConfig.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseConfig.c + +eclipseWin.obj: ../eclipseOS.h ../eclipseUnicode.h eclipseWin.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj eclipseWin.c + +eclipseWinCommon.obj: ../eclipseCommon.h eclipseWinCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj eclipseWinCommon.c + +eclipseJNI.obj: ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.c + $(CC) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseJNI.c + +eclipseShm.obj: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseShm.c + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) $(RES) + $(link) $(LFLAGS) -out:$(PROGRAM_OUTPUT) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) + +#the console version needs a flag set, should look for a better way to do this +$(CONSOLE): $(MAIN_OBJS) $(COMMON_OBJS) + del -f eclipseConfig.obj aeclipseConfig.obj + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) -D_WIN32_CONSOLE /FoeclipseConfig.obj ../eclipseConfig.c + $(link) $(CONSOLEFLAGS) -out:$(CONSOLE) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(link) $(DLL_LFLAGS) -out:$(PROGRAM_LIBRARY) $(DLL_OBJS) $(COMMON_OBJS) $(DLL_LIBS) + +$(RES): $(PROGRAM_NAME).rc + $(rc) -r -fo $(RES) eclipse.rc + +install: all + copy $(EXEC) $(OUTPUT_DIR) + del -f $(EXEC) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) + +clean: + del $(EXEC) $(DLL) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak new file mode 100644 index 000000000..f1faaabca --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak @@ -0,0 +1,107 @@ +#****************************************************************************** +# Copyright (c) 2007, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +#******************************************************************************* + +# Makefile for creating the eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output dll library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - the location of the Java for JNI includes +NODEBUG=1 + +APPVER=4.0 +_WIN32_WINNT=0x0400 +_WIN32_IE=0x0300 + +!include <ntwin32.mak> +!include <..\make_version.mak> + +PROGRAM_OUTPUT=eclipse.exe +# Separate filename from extention +PROGRAM_NAME=$(PROGRAM_OUTPUT:.exe=) + +PROGRAM_LIBRARY = eclipse_$(LIB_VERSION).dll + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.obj +COMMON_OBJS = eclipseConfig.obj eclipseCommon.obj eclipseWinCommon.obj +DLL_OBJS = eclipse.obj eclipseWin.obj eclipseUtil.obj eclipseJNI.obj eclipseShm.obj + +LIBS = kernel32.lib user32.lib comctl32.lib msvcrt.lib bufferoverflowU.lib +DLL_LIBS = kernel32.lib user32.lib comctl32.lib gdi32.lib Advapi32.lib msvcrt.lib version.lib bufferoverflowU.lib +LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:windows -entry:wmainCRTStartup +CONSOLEFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:console -entry:wmainCRTStartup +#DLL_LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /RELEASE /NOLOGO -entry:_DllMainCRTStartup@12 -dll /BASE:0x72000000 /DLL +DLL_LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /RELEASE /NOLOGO -dll /BASE:0x72000000 /DLL +RES = $(PROGRAM_NAME).res +EXEC = $(PROGRAM_OUTPUT) +CONSOLE = $(PROGRAM_NAME)c.exe +DLL = $(PROGRAM_LIBRARY) +DEBUG = #$(cdebug) +wcflags = -DUNICODE -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 \ + $(cflags) +all: $(EXEC) $(DLL) $(CONSOLE) + +eclipseMain.obj: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseMain.c + +eclipseCommon.obj: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseCommon.c + +eclipse.obj: ../eclipseOS.h ../eclipseUnicode.h ../eclipse.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipse.c + +eclipseUtil.obj: ../eclipseUtil.h ../eclipseUnicode.h ../eclipseUtil.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseUtil.c + +eclipseConfig.obj: ../eclipseConfig.h ../eclipseUnicode.h ../eclipseConfig.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseConfig.c + +eclipseWin.obj: ../eclipseOS.h ../eclipseUnicode.h eclipseWin.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj eclipseWin.c + +eclipseWinCommon.obj: ../eclipseCommon.h eclipseWinCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj eclipseWinCommon.c + +eclipseJNI.obj: ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.c + $(CC) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseJNI.c + +eclipseShm.obj: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(DEBUG) $(wcflags) $(cvarsdll) /Fo$*.obj ../eclipseShm.c + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) $(RES) + $(link) $(LFLAGS) -out:$(PROGRAM_OUTPUT) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) + +#the console version needs a flag set, should look for a better way to do this +$(CONSOLE): $(MAIN_OBJS) $(COMMON_OBJS) + del -f eclipseConfig.obj aeclipseConfig.obj + $(cc) $(DEBUG) $(wcflags) $(cvarsdll) -D_WIN32_CONSOLE /FoeclipseConfig.obj ../eclipseConfig.c + $(link) $(CONSOLEFLAGS) -out:$(CONSOLE) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(link) $(DLL_LFLAGS) -out:$(PROGRAM_LIBRARY) $(DLL_OBJS) $(COMMON_OBJS) $(DLL_LIBS) + +$(RES): $(PROGRAM_NAME).rc + $(rc) -r -fo $(RES) eclipse.rc + +install: all + copy $(EXEC) $(OUTPUT_DIR) + del -f $(EXEC) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) + +clean: + del $(EXEC) $(DLL) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/make_win64_ia64.mak b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64_ia64.mak new file mode 100644 index 000000000..5d9ff5c86 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64_ia64.mak @@ -0,0 +1,108 @@ +#****************************************************************************** +# Copyright (c) 2000, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* + +# Makefile for creating the eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output dll library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - the location of the Java for JNI includes +NODEBUG=1 +!include <ntwin32.mak> +!include <..\make_version.mak> + +PROGRAM_LIBRARY = eclipse_$(LIB_VERSION).dll + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.obj +COMMON_OBJS = eclipseConfig.obj eclipseCommon.obj eclipseWinCommon.obj +DLL_OBJS = eclipse.obj eclipseWin.obj eclipseUtil.obj eclipseJNI.obj eclipseShm.obj + +# using dynamic lib +#LIBS = kernel32.lib user32.lib comctl32.lib msvcrt.lib +#DLL_LIBS = kernel32.lib user32.lib comctl32.lib gdi32.lib Advapi32.lib msvcrt.lib version.lib + +LIBS = kernel32.lib user32.lib comctl32.lib libcmt.lib bufferoverflowU.lib +DLL_LIBS = kernel32.lib user32.lib comctl32.lib gdi32.lib Advapi32.lib libcmt.lib version.lib bufferoverflowU.lib +# LIBS = kernel32.lib user32.lib gdi32.lib comctl32.lib bufferoverflowu.lib +# LFLAGS = /INCREMENTAL:NO /NOLOGO -subsystem:windows -entry:wmainCRTStartup -machine:IA64 + +# was: windows +LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:windows -entry:wmainCRTStartup -machine:IA64 +CONSOLEFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:console -entry:wmainCRTStartup -machine:IA64 +DLL_LFLAGS = /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO /PDB:NONE -entry:_DllMainCRTStartup -dll /BASE:0x72000000 /DLL -machine:IA64 +RES = eclipse.res +EXEC = eclipse.exe +CONSOLE = eclipsec.exe +DLL = $(PROGRAM_LIBRARY) +DEBUG = #$(cdebug) +wcflags = -DUNICODE -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 \ + $(cflags) -D_CRT_SECURE_NO_WARNINGS -D_CRT_NON_CONFORMING_SWPRINTFS +all: $(EXEC) $(DLL) $(CONSOLE) + +eclipseMain.obj: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseMain.c + +eclipseCommon.obj: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseCommon.c + +eclipse.obj: ../eclipseOS.h ../eclipseUnicode.h ../eclipse.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipse.c + +eclipseUtil.obj: ../eclipseUtil.h ../eclipseUnicode.h ../eclipseUtil.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseUtil.c + +eclipseConfig.obj: ../eclipseConfig.h ../eclipseUnicode.h ../eclipseConfig.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseConfig.c + +eclipseWin.obj: ../eclipseOS.h ../eclipseUnicode.h eclipseWin.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj eclipseWin.c + +eclipseWinCommon.obj: ../eclipseCommon.h eclipseWinCommon.c + $(cc) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj eclipseWinCommon.c + +eclipseJNI.obj: ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.c + $(CC) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseJNI.c + +eclipseShm.obj: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(DEBUG) $(wcflags) $(cvars) /Fo$*.obj ../eclipseShm.c + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) $(RES) + $(link) $(LFLAGS) -out:$(PROGRAM_OUTPUT) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) +#$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) $(RES) +# $(link) $(LFLAGS) -out:$(PROGRAM_OUTPUT) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) + +#the console version needs a flag set, should look for a better way to do this +$(CONSOLE): $(MAIN_OBJS) $(COMMON_OBJS) + del -f eclipseConfig.obj aeclipseConfig.obj + $(cc) $(DEBUG) $(wcflags) $(cvars) -D_WIN32_CONSOLE /FoeclipseConfig.obj ../eclipseConfig.c + $(link) $(CONSOLEFLAGS) -out:$(CONSOLE) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + $(link) $(DLL_LFLAGS) -out:$(PROGRAM_LIBRARY) $(DLL_OBJS) $(COMMON_OBJS) $(DLL_LIBS) + +$(RES): eclipse.rc + $(rc) -v -r -fo $(RES) eclipse.rc + +install: all + copy $(EXEC) $(OUTPUT_DIR) + del -f $(EXEC) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) + +clean: + del $(EXEC) $(DLL) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/.cvsignore b/features/org.eclipse.equinox.executable.feature/library/wpf/.cvsignore new file mode 100644 index 000000000..b5e85ecb0 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/.cvsignore @@ -0,0 +1,12 @@ +*.obj +eclipse.exe +eclipse.res +*.pdb +*.exp +*.lib +eclipse_*.dll +com_*.dll +eclipsec.exe +eclipsec.exe.manifest +eclipse_*.dll.manifest +eclipse.exe.manifest diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/build.bat b/features/org.eclipse.equinox.executable.feature/library/wpf/build.bat new file mode 100644 index 000000000..57e1d7525 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/build.bat @@ -0,0 +1,127 @@ +@rem ******************************************************************************* +@rem Copyright (c) 2000, 2009 IBM Corporation and others. +@rem All rights reserved. This program and the accompanying materials +@rem are made available under the terms of the Eclipse Public License v1.0 +@rem which accompanies this distribution, and is available at +@rem http://www.eclipse.org/legal/epl-v10.html +@rem +@rem Contributors: +@rem IBM Corporation - initial API and implementation +@rem Kevin Cornell (Rational Software Corporation) +@rem ********************************************************************** +@rem +@rem Usage: sh build.sh [<optional switches>] [clean] +@rem +@rem where the optional switches are: +@rem -output <PROGRAM_OUTPUT> - executable filename ("eclipse") +@rem -library <PROGRAM_LIBRARY>- dll filename (eclipse.dll) +@rem -os <DEFAULT_OS> - default Eclipse "-os" value (qnx) +@rem -arch <DEFAULT_OS_ARCH> - default Eclipse "-arch" value (x86) +@rem -ws <DEFAULT_WS> - default Eclipse "-ws" value (photon) +@rem -java <JAVA_HOME> - location of a Java SDK for JNI headers +@rem +@rem +@rem This script can also be invoked with the "clean" argument. +@rem +@rem NOTE: The C compiler needs to be setup. This script has been +@rem tested against Microsoft Visual C and C++ Compiler 6.0. +@rem +@rem Uncomment the lines below and edit MSVC_HOME to point to the +@rem correct root directory of the compiler installation, if you +@rem want this to be done by this script. +@rem +@rem ****** +@echo off + +IF x.%1==x.x86 shift + +rem ***** +rem Javah +rem ***** +IF x."%JAVA_HOME%"==x. set JAVA_HOME="S:\swt-builddir\ibm-java2-sdk-50-win-i386" +set javaHome=%JAVA_HOME% + +:MSVC + +call "S:\swt-builddir\MSSDKs\Microsoft SDK 6.0 Vista\Bin\setenv.cmd" /x86 /vista +:MAKE + +rem -------------------------- +rem Define default values for environment variables used in the makefiles. +rem -------------------------- +set programOutput=eclipse.exe +set programLibrary=eclipse.dll +set defaultOS=win32 +set defaultOSArch=x86 +set defaultWS=wpf +set makefile=make_wpf.mak +set OS=Windows + +rem -------------------------- +rem Parse the command line arguments and override the default values. +rem -------------------------- +set extraArgs= +:WHILE +if "%1" == "" goto WHILE_END + if "%2" == "" goto LAST_ARG + + if "%1" == "-os" ( + set defaultOS=%2 + shift + goto NEXT ) + if "%1" == "-arch" ( + set defaultOSArch=%2 + shift + goto NEXT ) + if "%1" == "-ws" ( + set defaultWS=%2 + shift + goto NEXT ) + if "%1" == "-output" ( + set programOutput=%2 + shift + goto NEXT ) + if "%1" == "-library" ( + set programLibrary=%2 + shift + goto NEXT ) + if "%1" == "-java" ( + set javaHome=%2 + shift + goto NEXT ) +:LAST_ARG + set extraArgs=%extraArgs% %1 + +:NEXT + shift + goto WHILE +:WHILE_END + +rem -------------------------- +rem Set up environment variables needed by the makefile. +rem -------------------------- +set PROGRAM_OUTPUT=%programOutput% +set PROGRAM_LIBRARY=%programLibrary% +set DEFAULT_OS=%defaultOS% +set DEFAULT_OS_ARCH=%defaultOSArch% +set DEFAULT_WS=%defaultWS% +set EXEC_DIR=..\..\.\..\..\rt.equinox.binaries\org.eclipse.equinox.executable +set OUTPUT_DIR=%EXEC_DIR%\bin\%defaultWS%\%defaultOS%\%defaultOSArch% +set JAVA_HOME=%javaHome% + +rem -------------------------- +rem Run nmake to build the executable. +rem -------------------------- +if "%extraArgs%" == "" goto MAKE_ALL + +nmake -f %makefile% %extraArgs% +goto DONE + +:MAKE_ALL +echo Building %OS% launcher. Defaults: -os %DEFAULT_OS% -arch %DEFAULT_OS_ARCH% -ws %DEFAULT_WS% +nmake -f %makefile% clean +nmake -f %makefile% %1 %2 %3 %4 +goto DONE + + +:DONE diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/build.xml b/features/org.eclipse.equinox.executable.feature/library/wpf/build.xml new file mode 100644 index 000000000..f4b96fe70 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/build.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project default="build_eclipse" basedir="."> + +<target name="build_eclipse"> + <exec dir="." executable="${basedir}\build.bat"> + <arg line="install"/> + </exec> + <eclipse.refreshLocal resource="org.eclipse.equinox.executable" depth="infinite" /> +</target> + +<target name="clean"> + <tstamp/> + <exec dir="." executable="${basedir}\build.bat"> + <arg line="clean"/> + </exec> +</target> + +</project>
\ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/com.c b/features/org.eclipse.equinox.executable.feature/library/wpf/com.c new file mode 100644 index 000000000..35ce38514 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/com.c @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include <jni.h> +#include <ole2.h> + +#define COM_NATIVE(func) Java_org_eclipse_equinox_launcher_JNIBridge_##func + +JNIEXPORT jint JNICALL COM_NATIVE(OleInitialize) + (JNIEnv *env, jclass that, jint arg0) +{ + return (jint)OleInitialize((LPVOID)arg0); +} + +JNIEXPORT void JNICALL COM_NATIVE(OleUninitialize) + (JNIEnv *env, jclass that) +{ + OleUninitialize(); +} + diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.ico b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.ico Binary files differnew file mode 100644 index 000000000..9fb5b5b94 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.ico diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.rc b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.rc new file mode 100644 index 000000000..874a4b94e --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipse.rc @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#define ECLIPSE_ICON 401 + +#include "windows.h" +#include "winver.h" + + +ECLIPSE_ICON ICON DISCARDABLE "eclipse.ico" + +//CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "eclipse.exe.manifest" + diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpf.cpp b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpf.cpp new file mode 100644 index 000000000..f96523995 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpf.cpp @@ -0,0 +1,561 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Kevin Cornell (Rational Software Corporation) + *******************************************************************************/ + +extern "C" { + +#include "eclipseOS.h" +#include "eclipseUtil.h" +#include "eclipseCommon.h" +#include "eclipseJNI.h" + +#include <process.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +using namespace System; +using namespace System::IO; +using namespace System::Windows; +using namespace System::Windows::Input; +using namespace System::Windows::Media; +using namespace System::Windows::Media::Imaging; +using namespace System::Windows::Controls; +using namespace System::Windows::Threading; +using namespace System::Runtime::InteropServices; +using namespace System::ComponentModel; + + +/* Global Variables */ +_TCHAR* defaultVM = _T("javaw.exe"); +_TCHAR* consoleVM = _T("java.exe"); +_TCHAR* vmLibrary = _T("jvm.dll"); +_TCHAR* shippedVMDir = _T("jre\\bin\\"); + +/* Define the window system arguments for the Java VM. */ +static _TCHAR* argVM[] = { NULL }; + +/* Define local variables for running the JVM and detecting its exit. */ +static int jvmProcess = 0; +static JavaResults* jvmResults = NULL; +static int jvmExitTimeout = 100; +static int jvmExitTimerId = 99; + +static void CALLBACK detectJvmExit (); +static _TCHAR* checkVMRegistryKey(HKEY jrekey, _TCHAR* subKeyName); +static void adjustSearchPath( _TCHAR * vmLibrary ); +static _TCHAR* findLib( _TCHAR* command ); + +/* define default locations in which to find the jvm shared library + * these are paths relative to the java exe, the shared library is + * for example jvmLocations[0] + dirSeparator + vmLibrary */ +#define MAX_LOCATION_LENGTH 25 /* none of the jvmLocations strings should be longer than this */ +static const _TCHAR* jvmLocations [] = { _T("j9vm"), _T("..\\jre\\bin\\j9vm"), + _T("client"), _T("..\\jre\\bin\\client"), + _T("server"), _T("..\\jre\\bin\\server"), + _T("classic"), _T("..\\jre\\bin\\classic"), + _T("jrockit"), _T("..\\jre\\bin\\jrockit"), + NULL }; +/* for detecting sun vms */ +typedef struct { + WORD language; + WORD codepage; +} TRANSLATIONS; + +#define COMPANY_NAME_KEY _T_ECLIPSE("\\StringFileInfo\\%04x%04x\\CompanyName") +#define SUN_MICROSYSTEMS _T_ECLIPSE("Sun Microsystems") + +delegate void NoArgsHandler (); + +public ref class Globals { +public: + static Window^ window = nullptr; + static DispatcherFrame^ frame = nullptr; + + static void HandleDispatcherInactive (Object^ o, EventArgs^ e) { + if (frame != nullptr) frame->Continue = false; + } + static void HandleClosing (Object^ o, CancelEventArgs^ e) { + window = nullptr; + } + static void HandleTimer (Object^ o, EventArgs^ e) { + detectJvmExit(); + if (jvmProcess == 0) { + if (frame != nullptr) { + frame->Continue = false; + } + } + } + static void CloseWindow () { + if (window != nullptr) { + window->Close(); + window = nullptr; + } + } +}; + + +/* Show the Splash Window + * + * Open the bitmap, insert into the splash window and display it. + * + */ +int showSplash( const _TCHAR* featureImage ) +{ + static int splashing = 0; + + if(splashing) { + /*splash screen is already showing, do nothing */ + return 0; + } + if (featureImage == NULL) + return -1; + + /* if Java was started first and is calling back to show the splash, we might not + * have initialized the window system yet + */ + initWindowSystem(0, NULL, 1); + + /* Load the bitmap for the feature. */ + BitmapSource^ image = nullptr; + if (featureImage != NULL) { + String^ string = gcnew String (featureImage); + if (File::Exists (string)) { + Uri^ uri = gcnew Uri (string); + image = gcnew BitmapImage (uri); + } + } + + /* If the bitmap could not be found, return an error. */ + if (image == nullptr) + return ERROR_FILE_NOT_FOUND; + + /* Create a window that has no decorations. */ + Window^ window = Globals::window = gcnew Window(); + window->Closing += gcnew CancelEventHandler(&Globals::HandleClosing); + window->WindowStyle = WindowStyle::None; + window->ShowInTaskbar = false; + window->ResizeMode = ResizeMode::NoResize; + window->WindowStartupLocation = WindowStartupLocation::CenterScreen; + KeyboardNavigation::SetTabNavigation (window, KeyboardNavigationMode::None); + + Grid^ grid = gcnew Grid(); + GridLength length (1, GridUnitType::Auto); + ColumnDefinition^ column = gcnew ColumnDefinition(); + grid->ColumnDefinitions->Add (column); + column = gcnew ColumnDefinition(); + column->Width = length; + grid->ColumnDefinitions->Add (column); + RowDefinition^ row = gcnew RowDefinition (); + row->Height = length; + grid->RowDefinitions->Add (row); + row = gcnew RowDefinition (); + grid->RowDefinitions->Add (row); + row = gcnew RowDefinition (); + row->Height = length; + grid->RowDefinitions->Add (row); + window->Content = grid; + + Canvas^ canvas = gcnew Canvas (); + canvas->FocusVisualStyle = nullptr; + canvas->Focusable = true; + Grid::SetRow (canvas, 1); + Grid::SetColumn (canvas, 0); + grid->Children->Add (canvas); + + ImageBrush^ brush = gcnew ImageBrush(image); + canvas->Background = brush; + + window->Width = image->Width; + window->Height = image->Height; + window->Show(); + + splashing = 1; + + /* Process messages */ + dispatchMessages(); + return 0; +} + +void dispatchMessages() { + DispatcherFrame^ frame = gcnew DispatcherFrame(); + Globals::frame = frame; + EventHandler^ handler = gcnew EventHandler (&Globals::HandleDispatcherInactive); + Dispatcher^ dispatcher = Dispatcher::CurrentDispatcher; + DispatcherHooks^ hooks = dispatcher->Hooks; + hooks->DispatcherInactive += handler; + Dispatcher::PushFrame (frame); + hooks->DispatcherInactive -= handler; + Globals::frame = nullptr; +} + +jlong getSplashHandle() { + Window^ window = Globals::window; + return (jlong)(int)GCHandle::ToIntPtr(GCHandle::Alloc(window)); +} + +void takeDownSplash() { + if (false) { + NoArgsHandler^ handler = gcnew NoArgsHandler(&Globals::CloseWindow); + Dispatcher::CurrentDispatcher->BeginInvoke(DispatcherPriority::Send, handler); + } else { + Window^ window = Globals::window; + if(window != nullptr) { + window->Close (); + window = nullptr; + dispatchMessages(); + } + } +} + +/* Get the window system specific VM args */ +_TCHAR** getArgVM( _TCHAR *vm ) +{ + return argVM; +} + +/* Local functions */ + +/* + * Find the VM shared library starting from the java executable + */ +_TCHAR * findVMLibrary( _TCHAR* command ) { + _TCHAR* lib = findLib(command); + if( lib != NULL ) { + adjustSearchPath(lib); + } + return lib; +} + +void adjustSearchPath( _TCHAR* vmLib ){ + _TCHAR ** paths; + _TCHAR * path = NULL, *newPath = NULL; + _TCHAR * buffer, *c; + int i, length; + int needAdjust = 0, freePath = 0; + + /* we want the directory containing the library, and the parent directory of that */ + paths = getVMLibrarySearchPath(vmLib); + + /* first call to GetEnvironmentVariable tells us how big to make the buffer */ + length = GetEnvironmentVariable(_T_ECLIPSE("PATH"), path, 0); + if (length > 0) { + path = (_TCHAR*)malloc(length * sizeof(_TCHAR)); + GetEnvironmentVariable(_T_ECLIPSE("PATH"), path, length); + needAdjust = !containsPaths(path, paths); + freePath = 1; + } else { + path = _T_ECLIPSE(""); + freePath = 0; + needAdjust = 1; + } + + if (needAdjust) { + c = concatStrings(paths); + newPath = (_TCHAR*)malloc((_tcslen(c) + length + 1) * sizeof(_TCHAR)); + _stprintf(newPath, _T_ECLIPSE("%s%s"), c, path); + SetEnvironmentVariable( _T_ECLIPSE("PATH"), newPath); + free(c); + free(newPath); + } + + for (i = 0; i < 2 && paths[i] != NULL; i++) + free(paths[i]); + free(paths); + if (freePath) + free(path); +} + +static _TCHAR* findLib( _TCHAR* command ) { + int i, j; + int pathLength; + struct _stat stats; + _TCHAR * path; /* path to resulting jvm shared library */ + _TCHAR * location; /* points to begining of jvmLocations section of path */ + + /* for looking in the registry */ + HKEY jreKey = NULL; + DWORD length = MAX_PATH; + _TCHAR keyName[MAX_PATH]; + _TCHAR * jreKeyName; + + if (command != NULL) { + location = lastDirSeparator( command ) + 1; + + /*check first to see if command already points to the library */ + if (isVMLibrary(command)) { + if (_tstat( command, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + return command; /* exists */ + return NULL; /* doesn't exist */ + } + + pathLength = location - command; + path = (_TCHAR *)malloc((pathLength + MAX_LOCATION_LENGTH + 1 + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); + _tcsncpy(path, command, pathLength); + location = &path[pathLength]; + + /* + * We are trying base/jvmLocations[*]/vmLibrary + * where base is the directory containing the given java command, normally jre/bin + */ + i = -1; + while(jvmLocations[++i] != NULL) { + _stprintf(location, _T_ECLIPSE("%s%c%s"), jvmLocations[i], dirSeparator, vmLibrary); + if (_tstat( path, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /* found it */ + return path; + } + } + } + + /* Not found yet, try the registry, we will use the first vm >= 1.4 */ + jreKeyName = _T("Software\\JavaSoft\\Java Runtime Environment"); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, jreKeyName, 0, KEY_READ, &jreKey) == ERROR_SUCCESS) { + if(RegQueryValueEx(jreKey, _T_ECLIPSE("CurrentVersion"), NULL, NULL, (LPBYTE)&keyName, &length) == ERROR_SUCCESS) { + path = checkVMRegistryKey(jreKey, keyName); + if (path != NULL) { + RegCloseKey(jreKey); + return path; + } + } + j = 0; + length = MAX_PATH; + while (RegEnumKeyEx(jreKey, j++, keyName, &length, 0, 0, 0, 0) == ERROR_SUCCESS) { + /*look for a 1.4 or 1.5 vm*/ + if( _tcsncmp(_T("1.4"), keyName, 3) <= 0 ) { + path = checkVMRegistryKey(jreKey, keyName); + if (path != NULL) { + RegCloseKey(jreKey); + return path; + } + } + } + RegCloseKey(jreKey); + } + return NULL; +} + +/* + * Read the subKeyName subKey of jreKey and look to see if it has a Value + * "RuntimeLib" which points to a jvm library we can use + * + * Does not close jreKey + */ +static _TCHAR* checkVMRegistryKey(HKEY jreKey, _TCHAR* subKeyName) { + _TCHAR value[MAX_PATH]; + HKEY subKey = NULL; + DWORD length = MAX_PATH; + _TCHAR *result = NULL; + struct _stat stats; + + if(RegOpenKeyEx(jreKey, subKeyName, 0, KEY_READ, &subKey) == ERROR_SUCCESS) { + /*The RuntimeLib value should point to the library we want*/ + if(RegQueryValueEx(subKey, _T("RuntimeLib"), NULL, NULL, (LPBYTE)&value, &length) == ERROR_SUCCESS) { + if (_tstat( value, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0) + { /*library exists*/ + result = _tcsdup(value); + } + } + RegCloseKey(subKey); + } + return result; +} + +static _TCHAR* buildCommandLine( _TCHAR* program, _TCHAR* args[] ) +{ + int index, length = 0, slash; + _TCHAR *commandLine, *ch, *space; + + /* + * Build the command line. Any argument with spaces must be in + * double quotes in the command line. + */ + if(program != NULL) + length = _tcslen(program) + 1; + for (index = 0; args[index] != NULL; index++) + { + /* String length plus space character */ + length += _tcslen( args[ index ] ) + 1; + /* Quotes + potential escaping '\' */ + if (_tcschr( args[ index ], _T(' ') ) != NULL) length += 3; + } + + commandLine = ch = (_TCHAR *)malloc ( (length + 1) * sizeof(_TCHAR) ); + if (program != NULL) { + _tcscpy(ch, program); + ch += _tcslen(program); + *ch++ = _T(' '); + } + for (index = 0; args[index] != NULL; index++) + { + space = _tcschr( args[ index ], _T(' ')); + if (space != NULL) *ch++ = _T('\"'); + _tcscpy( ch, args[index] ); + ch += _tcslen( args[index] ); + if (space != NULL) { + if ( *(ch - 1) == _T('\\') ) { + /* escape a trailing unescaped '\' or it will escape our closing '"' and mess things up */ + slash = 1; + while ( *(ch - 1 - slash) == _T('\\')) slash++; + if (slash % 2) *ch++ = _T('\\'); + } + *ch++ = _T('\"'); + } + *ch++ = _T(' '); + } + *ch = _T('\0'); + return commandLine; +} +void restartLauncher( _TCHAR* program, _TCHAR* args[] ) +{ + _TCHAR* commandLine = buildCommandLine(program, args); + + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + GetStartupInfo(&si); + if (CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle( pi.hThread ); + } + } + free(commandLine); +} + +JavaResults* launchJavaVM( _TCHAR* args[] ) +{ + MSG msg; + _TCHAR* commandLine; + jvmProcess = -1; + commandLine = buildCommandLine(NULL, args); + jvmResults = (JavaResults*) malloc(sizeof(JavaResults)); + memset(jvmResults, 0, sizeof(JavaResults)); + + /* + * Start the Java virtual machine. Use CreateProcess() instead of spawnv() + * otherwise the arguments cannot be freed since spawnv() segments fault. + */ + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + GetStartupInfo(&si); + if (CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle( pi.hThread ); + jvmProcess = (int)pi.hProcess; + } + } + + free( commandLine ); + + /* If the child process (JVM) would not start */ + if (jvmProcess == -1) + { + /* Return the error number. */ + jvmResults->launchResult = errno; + jvmProcess = 0; + } + + /* else */ + else + { + + /* Set a timer to detect JVM process termination. */ + DispatcherTimer^ timer = gcnew DispatcherTimer(); + timer->Interval = TimeSpan::FromMilliseconds (jvmExitTimeout); + timer->Tick += gcnew EventHandler(&Globals::HandleTimer); + + /* Process messages until the JVM terminates. + This launcher process must continue to process events until the JVM exits + or else Windows 2K will hang if the desktop properties (e.g., background) are + changed by the user. Windows does a SendMessage() to every top level window + process, which blocks the caller until the process responds. */ + + DispatcherFrame^ frame = gcnew DispatcherFrame(); + Globals::frame = frame; + timer->Start(); + Dispatcher::PushFrame(frame); + Globals::frame = nullptr; + timer->Stop(); + + } + + /* Return the exit code from the JVM. */ + return jvmResults; +} + +/* Detect JVM Process Termination */ +static void CALLBACK detectJvmExit () +{ + DWORD exitCode; + /* If the JVM process has terminated */ + if (!GetExitCodeProcess( (HANDLE)jvmProcess, &exitCode ) || + exitCode != STILL_ACTIVE) + { + /* Save the JVM exit code. This should cause the loop in launchJavaVM() to exit. */ + jvmResults->runResult = exitCode; + jvmProcess = 0; + } +} + +void processVMArgs(_TCHAR **vmargs[] ) { +// /* nothing yet */ +} + +JavaResults* startJavaVM( _TCHAR* libPath, _TCHAR* vmArgs[], _TCHAR* progArgs[], _TCHAR* jarFile ) +{ + return startJavaJNI(libPath, vmArgs, progArgs, jarFile); +} + +int isSunVM( _TCHAR * javaVM, _TCHAR * jniLib ) { + _TCHAR *vm = (jniLib != NULL) ? jniLib : javaVM; + int result = 0; + DWORD infoSize; + DWORD handle; + void * info; + + _TCHAR * key, *value; + size_t i; + int valueSize; + + if (vm == NULL) + return 0; + + infoSize = GetFileVersionInfoSize(vm, &handle); + if (infoSize > 0) { + info = malloc(infoSize); + if (GetFileVersionInfo(vm, 0, infoSize, info)) { + TRANSLATIONS * translations; + int translationsSize; + VerQueryValue(info, _T_ECLIPSE("\\VarFileInfo\\Translation"), (LPVOID *) &translations, (PUINT)&translationsSize); + + /* this size is only right because %04x is 4 characters */ + key = (_TCHAR *) malloc( (_tcslen(COMPANY_NAME_KEY) + 1) * sizeof(_TCHAR)); + for (i = 0; i < (translationsSize / sizeof(TRANSLATIONS)); i++) { + _stprintf(key, COMPANY_NAME_KEY, translations[i].language, translations[i].codepage); + + VerQueryValue(info, key, (LPVOID *)&value, (PUINT)&valueSize); + if (_tcsncmp(value, SUN_MICROSYSTEMS, _tcslen(SUN_MICROSYSTEMS)) == 0) { + result = 1; + break; + } + } + free(key); + } + free(info); + } + return result; +} + +int reuseWorkbench(_TCHAR** filePath, int timeout) { + /* not implemented for WPF */ + return -1; +} +} // extern "C" diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpfCommon.cpp b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpfCommon.cpp new file mode 100644 index 000000000..03ce3fceb --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/eclipseWpfCommon.cpp @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Andrew Niefer + *******************************************************************************/ + + +extern "C" { + +#include "eclipseCommon.h" +#include "eclipseOS.h" + +#include <windows.h> +#include <stdlib.h> +#include <commctrl.h> + + +#define ECLIPSE_ICON 401 + +_TCHAR dirSeparator = _T('\\'); +_TCHAR pathSeparator = _T(';'); + +static int initialized = 0; + +/* Load the specified shared library + */ +void * loadLibrary( _TCHAR * library ){ + return (void *)LoadLibrary(library); +} + +/* Unload the shared library + */ +void unloadLibrary( void * handle ){ + FreeLibrary((HMODULE)handle); +} + +/* Find the given symbol in the shared library + */ +void * findSymbol( void * handle, _TCHAR * symbol ){ + char * str = NULL; + void * result; + + str = toNarrow(symbol); + result = GetProcAddress((HMODULE)handle, str); + free(str); + return result; +} + +_TCHAR* resolveSymlinks( _TCHAR* path ) { + /* no symlinks on windows */ + return path; +} + +} //end extern C + +/* Display a Message */ +void displayMessage( _TCHAR* title, _TCHAR* message ) +{ + if(!initialized) + initWindowSystem(0, NULL, 0); + + System::String^ titleStr = gcnew System::String (title); + System::String^ messageStr = gcnew System::String (message); + System::Windows::MessageBox::Show (messageStr, titleStr, System::Windows::MessageBoxButton::OK); +} + +/* Initialize Window System + * + * Create a pop window to display the bitmap image. + * + * Return the window handle as the data for the splash command. + * + */ +int initWindowSystem( int* pArgc, _TCHAR* argv[], int showSplash ) +{ + + if(initialized) + return 0; + initialized = 1; + return 0; +} diff --git a/features/org.eclipse.equinox.executable.feature/library/wpf/make_wpf.mak b/features/org.eclipse.equinox.executable.feature/library/wpf/make_wpf.mak new file mode 100644 index 000000000..1d92df461 --- /dev/null +++ b/features/org.eclipse.equinox.executable.feature/library/wpf/make_wpf.mak @@ -0,0 +1,113 @@ +#****************************************************************************** +# Copyright (c) 2000, 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Kevin Cornell (Rational Software Corporation) +#******************************************************************************* + +# Makefile for creating the eclipse launcher program. + +# This makefile expects the following environment variables set: +# +# PROGRAM_OUTPUT - the filename of the output executable +# PROGRAM_LIBRARY - the filename of the output dll library +# DEFAULT_OS - the default value of the "-os" switch +# DEFAULT_OS_ARCH - the default value of the "-arch" switch +# DEFAULT_WS - the default value of the "-ws" switch +# JAVA_HOME - the location of the Java for JNI includes +NODEBUG=1 +!include <..\make_version.mak> + +PROGRAM_LIBRARY = eclipse_$(LIB_VERSION).dll +PROGRAM_OUTPUT=eclipse.exe +# Separate filename from extention +PROGRAM_NAME=$(PROGRAM_OUTPUT:.exe=) + +# Define the object modules to be compiled and flags. +MAIN_OBJS = eclipseMain.obj +COMMON_OBJS = eclipseConfig.obj eclipseCommon.obj eclipseWpfCommon.obj +DLL_OBJS = eclipse.obj eclipseWpf.obj eclipseUtil.obj eclipseJNI.obj eclipseShm.obj + +LIBS = kernel32.lib msvcrt.lib mscoree.lib +DLL_LIBS = kernel32.lib Advapi32.lib msvcrt.lib version.lib +LFLAGS = -CLRTHREADATTRIBUTE:STA /NODEFAULTLIB:LIBCMT /INCREMENTAL:NO /LARGEADDRESSAWARE /RELEASE /NOLOGO -subsystem:windows,4.0 -entry:wmainCRTStartup +CONSOLEFLAGS = -CLRTHREADATTRIBUTE:STA /NODEFAULTLIB:LIBCMT /INCREMENTAL:NO /LARGEADDRESSAWARE /RELEASE /NOLOGO -subsystem:console,4.0 -entry:wmainCRTStartup +DLL_LFLAGS = -CLRTHREADATTRIBUTE:STA /NODEFAULTLIB:LIBCMT /INCREMENTAL:NO /LARGEADDRESSAWARE /PDB:NONE -dll /BASE:0x72000000 /DLL +RES = $(PROGRAM_NAME).res +EXEC = $(PROGRAM_OUTPUT) +CONSOLE = $(PROGRAM_NAME)c.exe +DLL = $(PROGRAM_LIBRARY) +DEBUG = #$(cdebug) + +CFLAGS = -c -DUNICODE -DVISTA -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NON_CONFORMING_SWPRINTFS -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ + -DDEFAULT_OS_ARCH="\"$(DEFAULT_OS_ARCH)\"" \ + -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ + -I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 \ + $(cflags) + +WPF_HOME = C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0 +DOTNET_HOME = C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 +CPPFLAGS = -clr /FU"$(WPF_HOME)\PresentationCore.dll" /FU"$(WPF_HOME)\PresentationFramework.dll" /FU$(DOTNET_HOME)\System.Data.dll /FU$(DOTNET_HOME)\System.dll /FU$(DOTNET_HOME)\System.Xml.dll /FU"$(WPF_HOME)\UIAutomationProvider.dll" /FU"$(WPF_HOME)\UIAutomationTypes.dll" /FU"$(WPF_HOME)\WindowsBase.dll" + + +all: $(EXEC) $(DLL) com $(CONSOLE) + +eclipseMain.obj: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseMain.c + +eclipseCommon.obj: ../eclipseCommon.h ../eclipseUnicode.h ../eclipseCommon.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseCommon.c + +eclipse.obj: ../eclipseOS.h ../eclipseUnicode.h ../eclipse.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipse.c + +eclipseUtil.obj: ../eclipseUtil.h ../eclipseUnicode.h ../eclipseUtil.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseUtil.c + +eclipseConfig.obj: ../eclipseConfig.h ../eclipseUnicode.h ../eclipseConfig.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseConfig.c + +eclipseWpf.obj: ../eclipseOS.h ../eclipseUnicode.h eclipseWpf.cpp + $(CC) $(DEBUG) $(CFLAGS) $(CPPFLAGS) $(cvarsdll) /Fo$*.obj eclipseWpf.cpp + +eclipseWpfCommon.obj: ../eclipseCommon.h eclipseWpfCommon.cpp + $(CC) $(DEBUG) $(CFLAGS) $(CPPFLAGS) $(cvarsdll) /Fo$*.obj eclipseWpfCommon.cpp + +eclipseJNI.obj: ../eclipseCommon.h ../eclipseOS.h ../eclipseJNI.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseJNI.c + +eclipseShm.obj: ../eclipseShm.h ../eclipseUnicode.h ../eclipseShm.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj ../eclipseShm.c + +$(EXEC): $(MAIN_OBJS) $(COMMON_OBJS) + rc.exe -r -fo $(RES) $(PROGRAM_NAME).rc + link $(LFLAGS) -out:$(PROGRAM_OUTPUT) $(MAIN_OBJS) $(COMMON_OBJS) $(RES) $(LIBS) + mt.exe -manifest $(PROGRAM_OUTPUT).manifest -outputresource:$(PROGRAM_OUTPUT);2 + +$(CONSOLE): $(MAIN_OBJS) $(COMMON_OBJS) + del -f eclipseConfig.obj + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) -D_WIN32_CONSOLE /FoeclipseConfig.obj ../eclipseConfig.c + link $(CONSOLEFLAGS) -out:$(CONSOLE) $(MAIN_OBJS) $(COMMON_OBJS) $(LIBS) + mt.exe -manifest $(PROGRAM_OUTPUT).manifest -outputresource:$(CONSOLE);2 + +$(DLL): $(DLL_OBJS) $(COMMON_OBJS) + link $(DLL_LFLAGS) -out:$(PROGRAM_LIBRARY) $(DLL_OBJS) $(COMMON_OBJS) $(DLL_LIBS) + mt.exe -manifest $(PROGRAM_LIBRARY).manifest -outputresource:$(PROGRAM_LIBRARY);2 + +com.obj: com.c + $(CC) $(DEBUG) $(CFLAGS) $(cvarsdll) /Fo$*.obj com.c + +com: com.obj + link /DLL -out:com_$(LIB_VERSION).dll com.obj ole32.lib + +install: all + copy $(EXEC) $(OUTPUT_DIR) + del -f $(EXEC) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) + +clean: + del $(EXEC) $(DLL) $(MAIN_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) *.manifest *.exp *.lib *.dll |