diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipse.c b/features/org.eclipse.equinox.executable.feature/library/eclipse.c index 9f826c09f2..a68868557b 100644 --- a/features/org.eclipse.equinox.executable.feature/library/eclipse.c +++ b/features/org.eclipse.equinox.executable.feature/library/eclipse.c @@ -256,6 +256,7 @@ static _TCHAR* defaultAction = NULL; /* default action for non '-' command li static _TCHAR* iniFile = NULL; /* the launcher.ini file set if --launcher.ini was specified */ static _TCHAR* gtkVersionString = NULL; /* GTK+ version specified by --launcher.GTK_version */ static _TCHAR* protectMode = NULL; /* Process protectMode specified via -protect, to trigger the reading of eclipse.ini in the configuration (Mac specific currently) */ +static _TCHAR** additionalVmargsPath = NULL; /* List of locations of files with extra vmargs that have higher priority over other vmargs */ /* variables for ee options */ static _TCHAR* eeExecutable = NULL; @@ -282,6 +283,7 @@ typedef struct #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 */ +#define EXPAND_PATH 32 /* value is a path, expands patterns like %name% with environment-variable strings */ static Option options[] = { { CONSOLE, &needConsole, VALUE_IS_FLAG, 0 }, @@ -307,7 +309,8 @@ static Option options[] = { { DEFAULTACTION,&defaultAction, 0, 2 }, { WS, &wsArg, 0, 2 }, { GTK_VERSION, >kVersionString, 0, 2 }, - { PROTECT, &protectMode, 0, 2 } }; + { PROTECT, &protectMode, 0, 2 }, + { ADDITIONAL_VMARGS, &additionalVmargsPath, ADJUST_PATH | EXPAND_PATH | VALUE_IS_LIST, -1 } }; static int optionsSize = (sizeof(options) / sizeof(options[0])); @@ -864,6 +867,8 @@ static void parseArgs(int* pArgc, _TCHAR* argv[]) { _TCHAR * next = argv[index + i + 1]; if (option->flag & ADJUST_PATH) next = checkPath(next, getProgramDir(), 0); + if (option->flag & EXPAND_PATH) + next = expandPath(next); if (next[0] != _T_ECLIPSE('-')) { if (option->flag & VALUE_IS_LIST) (*((_TCHAR***) option->value))[i] = next; @@ -996,15 +1001,36 @@ static _TCHAR** extractVMArgs(_TCHAR** launcherIniValues) { return NULL; } +/** Attempts to read the first configuration file + * If the file is not found, it will try the next one in the list + * Returns the arguments read from the file or NULL if no file was found */ +static _TCHAR** getAdditionalVMArgs() { + if (additionalVmargsPath == NULL) { + return NULL; + } + + int argc = 0; + _TCHAR** argv = NULL; + + for (_TCHAR** path = additionalVmargsPath; *path; path++) { + if (readConfigFile(*path, &argc, &argv) == 0) { + break; + } + } + + return argv; +} + //Reads the installation eclipse.ini file, reads a eclipse.ini from the configuration location, //and merge the VM arguments static _TCHAR** mergeConfigurationFilesVMArgs() { _TCHAR** userLauncherIniVMArgs = extractVMArgs(getLauncherIniFileFromConfiguration()); _TCHAR** configVMArgs = extractVMArgs(getConfigArgs()); + _TCHAR** additionalVMArgs = getAdditionalVMArgs(); - /* This always allocates new memory so we don't need to guess if it is safe - * to free later */ - return concatArgs(configVMArgs, userLauncherIniVMArgs); + /* This always allocates new memory so we don't need to guess if it is safe + * to free later */ + return concatArgs(concatArgs(configVMArgs, userLauncherIniVMArgs), additionalVMArgs); } static void adjustVMArgs(_TCHAR *javaVM, _TCHAR *jniLib, _TCHAR **vmArgv[]) { diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c index 9da16644ff..e301c7adb2 100644 --- a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.c @@ -541,6 +541,44 @@ _TCHAR* checkPath( _TCHAR* path, _TCHAR* programDir, int reverseOrder ) return result != NULL ? result : path; } +_TCHAR* expandPath(_TCHAR* inPath) { + _TCHAR buffer[MAX_PATH_LENGTH]; + _TCHAR variable[MAX_PATH_LENGTH]; + + _TCHAR* dstCur = &buffer[0]; + _TCHAR* srcCur = &inPath[0]; + + for(;;) { + _TCHAR* start = _tcschr(srcCur, _T_ECLIPSE('%')); + if (start == NULL) { + // No more variables + _tcscpy(dstCur, srcCur); + return _tcsdup(buffer); + } + _TCHAR* end = _tcschr(start + 1, _T_ECLIPSE('%')); + if (end == NULL) { + // Not a variable + *dstCur++ = *srcCur++; + continue; + } + _tcsncpy(variable, start + 1, end - start); + variable[end - start - 1] = _T_ECLIPSE('\0'); + _TCHAR* value = _tgetenv(variable); + if (value != NULL) { + // Found a variable + _tcsncpy(dstCur, srcCur, start - srcCur); + dstCur += start - srcCur; + _tcscpy(dstCur, value); + dstCur += _tcslen(value); + } else { + // Variable is not found + _tcsncpy(dstCur, srcCur, end - srcCur + 1); + dstCur += end - srcCur + 1; + } + srcCur = end + 1; + } +} + _TCHAR * lastDirSeparator(_TCHAR* str) { #ifndef _WIN32 return _tcsrchr(str, dirSeparator); diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h index 6c8cd2f877..55938e7127 100644 --- a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h @@ -53,6 +53,7 @@ #define OLD_ARGS_START _T_ECLIPSE("--launcher.oldUserArgsStart") #define OLD_ARGS_END _T_ECLIPSE("--launcher.oldUserArgsEnd") #define SKIP_OLD_ARGS _T_ECLIPSE("--launcher.skipOldUserArgs") +#define ADDITIONAL_VMARGS _T_ECLIPSE("--launcher.additionalVmargs") #define XXPERMGEN _T_ECLIPSE("-XX:MaxPermSize=") #define ADDMODULES _T_ECLIPSE("--add-modules") @@ -153,6 +154,14 @@ 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 ); +/** + * Expands environment-variable strings and replaces + * them with the values defined for the current user. + * + * Regardless of the platform, the same syntax is used: %VariableName%. + */ +extern _TCHAR* expandPath(_TCHAR* path); + extern _TCHAR * lastDirSeparator(_TCHAR* str); extern _TCHAR * firstDirSeparator(_TCHAR* str); diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c index ebd6abaf37..5bbfe4fa97 100644 --- a/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c +++ b/features/org.eclipse.equinox.executable.feature/library/eclipseConfig.c @@ -69,12 +69,21 @@ _TCHAR* getIniFile(_TCHAR* program, int consoleLauncher){ extension = config_file + _tcslen(config_file); } _tcscpy(extension, _T_ECLIPSE(".ini")); - if(consoleLauncher){ + struct _stat stats; + if(consoleLauncher && _tstat(config_file, &stats) != 0){ /* 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); + * removing the suffix from the end of the program name */ + static const _TCHAR* consoleLauncherSuffixes[] = { + _T_ECLIPSE("c"), // eclipsec.exe + _T_ECLIPSE("-cli"), // eclipse-cli.exe + NULL + }; + for (const _TCHAR** suffix = consoleLauncherSuffixes; *suffix; suffix++) { + size_t suffixLen = _tcslen(*suffix); + if (_tcsncmp(extension - suffixLen, *suffix, suffixLen) == 0) { + _tcscpy(extension - suffixLen, extension); + break; + } } } }