--- old/jdk/src/java.base/share/native/libjli/java.c 2016-08-08 16:30:45.000000000 -0700 +++ new/jdk/src/java.base/share/native/libjli/java.c 2016-08-08 16:30:44.000000000 -0700 @@ -69,7 +69,7 @@ static jboolean printUsage = JNI_FALSE; /* print and exit*/ static jboolean printXUsage = JNI_FALSE; /* print and exit*/ static jboolean dryRun = JNI_FALSE; /* initialize VM and exit */ -static char *showSettings = NULL; /* print but continue */ +static char *showSettings = NULL; /* print but continue */ static char *listModules = NULL; static const char *_program_name; @@ -99,17 +99,9 @@ * Prototypes for functions internal to launcher. */ static void SetClassPath(const char *s); -static void SetModulePath(const char *s); -static void SetUpgradeModulePath(const char *s); static void SetMainModule(const char *s); -static void SetAddModulesProp(const char *mods); -static void SetLimitModulesProp(const char *mods); -static void SetAddReadsProp(const jint n, const char *s); -static void SetAddExportsProp(const jint n, const char *s); -static void SetPatchProp(const jint n, const char *s); static void SelectVersion(int argc, char **argv, char **main_class); static void SetJvmEnvironment(int argc, char **argv); -static jboolean IsWhiteSpaceOptionArgument(const char* name); static jboolean ParseArguments(int *pargc, char ***pargv, int *pmode, char **pwhat, int *pret, const char *jrepath); @@ -133,6 +125,18 @@ static void DumpState(); static jboolean RemovableOption(char *option); +enum OptionKind { + LAUNCHER_OPTION = 0, + LAUNCHER_OPTION_WITH_ARGUMENT, + LAUNCHER_MAIN_OPTION, + VM_LONG_OPTION, + VM_LONG_OPTION_WITH_ARGUMENT, + VM_OPTION +}; + +static int GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue); +static jboolean IsOptionWithArgument(int argc, char **argv); + /* Maximum supported entries from jvm.cfg. */ #define INIT_MAX_KNOWN_VMS 10 @@ -162,6 +166,19 @@ static void FreeKnownVMs(); static jboolean IsWildCardEnabled(); +/* + * This reports error. VM will not be created and no usage is printed. + */ +#define REPORT_ERROR(AC_ok, AC_failure_message, AC_questionable_arg) \ + do { \ + if (!AC_ok) { \ + JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \ + printUsage = JNI_FALSE; \ + *pret = 1; \ + return JNI_FALSE; \ + } \ + } while (JNI_FALSE) + #define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \ do { \ if (AC_arg_count < 1) { \ @@ -511,17 +528,73 @@ } /* - * Test if the given option name has a whitespace separated argument. + * Test if the given name is one of the class path options. */ -jboolean -IsWhiteSpaceOptionArgument(const char* name) { +static jboolean +IsClassPathOption(const char* name) { return JLI_StrCmp(name, "-classpath") == 0 || JLI_StrCmp(name, "-cp") == 0 || - JLI_StrCmp(name, "-modulepath") == 0 || - JLI_StrCmp(name, "-mp") == 0 || - JLI_StrCmp(name, "-upgrademodulepath") == 0 || - JLI_StrCmp(name, "-addmods") == 0 || - JLI_StrCmp(name, "-limitmods") == 0; + JLI_StrCmp(name, "--class-path") == 0; +} + +/* + * Test if the given name is a launcher option taking the main entry point. + */ +static jboolean +IsLauncherMainOption(const char* name) { + return JLI_StrCmp(name, "--module") == 0 || + JLI_StrCmp(name, "-m") == 0; +} + +/* + * Test if the given name is a white-space launcher option. + */ +static jboolean +IsLauncherOption(const char* name) { + return IsClassPathOption(name) || + IsLauncherMainOption(name) || + JLI_StrCmp(name, "--list-modules") == 0; +} + +#ifndef OLD_MODULE_OPTIONS +/* + * Old module options for transition + */ +static jboolean +IsOldModuleOption(const char* name) { + return JLI_StrCmp(name, "-modulepath") == 0 || + JLI_StrCmp(name, "-mp") == 0 || + JLI_StrCmp(name, "-upgrademodulepath") == 0 || + JLI_StrCmp(name, "-addmods") == 0 || + JLI_StrCmp(name, "-limitmods") == 0; +} +#endif + +/* + * Test if the given name is a module-system white-space option that + * will be passed to the VM with its corresponding long-form option + * name and "=" delimiter. + */ +static jboolean +IsModuleOption(const char* name) { + return JLI_StrCmp(name, "--module-path") == 0 || + JLI_StrCmp(name, "-p") == 0 || + JLI_StrCmp(name, "--upgrade-module-path") == 0 || + JLI_StrCmp(name, "--add-modules") == 0 || + JLI_StrCmp(name, "--limit-modules") == 0 || + JLI_StrCmp(name, "--add-exports") == 0 || + JLI_StrCmp(name, "--add-reads") == 0 || + JLI_StrCmp(name, "--patch-module") == 0 || + IsOldModuleOption(name); +} + +/* + * Test if the given name has a white space option. + */ +jboolean +IsWhiteSpaceOption(const char* name) { + return IsModuleOption(name) || + IsLauncherOption(name); } /* @@ -559,7 +632,7 @@ continue; } } else { - if (IsWhiteSpaceOptionArgument(arg)) { + if (IsWhiteSpaceOption(arg)) { newArgv[newArgvIdx++] = arg; argi++; if (argi < argc) { @@ -701,7 +774,7 @@ if (i > 0) { char *prev = argv[i - 1]; // skip non-dash arg preceded by class path specifiers - if (*arg != '-' && IsWhiteSpaceOptionArgument(prev)) { + if (*arg != '-' && IsWhiteSpaceOption(prev)) { continue; } @@ -709,6 +782,7 @@ || JLI_StrCmp(arg, "-version") == 0 || JLI_StrCmp(arg, "-fullversion") == 0 || JLI_StrCmp(arg, "-help") == 0 + || JLI_StrCmp(arg, "--help") == 0 || JLI_StrCmp(arg, "-?") == 0 || JLI_StrCmp(arg, "-jar") == 0 || JLI_StrCmp(arg, "-X") == 0) { @@ -882,39 +956,16 @@ } static void -SetModulePath(const char *s) +AddLongFormOption(const char *option, const char *arg) { + static const char format[] = "%s=%s"; char *def; - const char *orig = s; - static const char format[] = "-Djdk.module.path=%s"; - if (s == NULL) - return; - s = JLI_WildcardExpandClasspath(s); - def = JLI_MemAlloc(sizeof(format) - - 2 /* strlen("%s") */ - + JLI_StrLen(s)); - sprintf(def, format, s); - AddOption(def, NULL); - if (s != orig) - JLI_MemFree((char *) s); -} + size_t def_len; -static void -SetUpgradeModulePath(const char *s) -{ - char *def; - const char *orig = s; - static const char format[] = "-Djdk.upgrade.module.path=%s"; - if (s == NULL) - return; - s = JLI_WildcardExpandClasspath(s); - def = JLI_MemAlloc(sizeof(format) - - 2 /* strlen("%s") */ - + JLI_StrLen(s)); - sprintf(def, format, s); + def_len = JLI_StrLen(option) + 1 + JLI_StrLen(arg) + 1; + def = JLI_MemAlloc(def_len); + JLI_Snprintf(def, def_len, format, option, arg); AddOption(def, NULL); - if (s != orig) - JLI_MemFree((char *) s); } static void @@ -939,46 +990,6 @@ AddOption(def, NULL); } -static void -SetAddModulesProp(const char *mods) { - size_t buflen = JLI_StrLen(mods) + 40; - char *prop = (char *)JLI_MemAlloc(buflen); - JLI_Snprintf(prop, buflen, "-Djdk.launcher.addmods=%s", mods); - AddOption(prop, NULL); -} - -static void -SetLimitModulesProp(const char *mods) { - size_t buflen = JLI_StrLen(mods) + 40; - char *prop = (char *)JLI_MemAlloc(buflen); - JLI_Snprintf(prop, buflen, "-Djdk.launcher.limitmods=%s", mods); - AddOption(prop, NULL); -} - -static void -SetAddReadsProp(const jint n, const char *s) { - size_t buflen = JLI_StrLen(s) + 40; - char *prop = (char *)JLI_MemAlloc(buflen); - JLI_Snprintf(prop, buflen, "-Djdk.launcher.addreads.%d=%s", n, s); - AddOption(prop, NULL); -} - -static void -SetAddExportsProp(const jint n, const char *s) { - size_t buflen = JLI_StrLen(s) + 40; - char *prop = (char *)JLI_MemAlloc(buflen); - JLI_Snprintf(prop, buflen, "-Djdk.launcher.addexports.%d=%s", n, s); - AddOption(prop, NULL); -} - -static void -SetPatchProp(const jint n, const char *s) { - size_t buflen = JLI_StrLen(s) + 40; - char *prop = (char *)JLI_MemAlloc(buflen); - JLI_Snprintf(prop, buflen, "-Djdk.launcher.patch.%d=%s", n, s); - AddOption(prop, NULL); -} - /* * The SelectVersion() routine ensures that an appropriate version of * the JRE is running. The specification for the appropriate version @@ -1003,6 +1014,7 @@ char *splash_jar_name = NULL; char *env_in; int res; + jboolean has_arg; /* * If the version has already been selected, set *main_class @@ -1033,9 +1045,11 @@ * This capability is no longer available with JRE versions 1.9 and later. * These command line options are reported as errors. */ + argc--; argv++; while ((arg = *argv) != 0 && *arg == '-') { + has_arg = IsOptionWithArgument(argc, argv); if (JLI_StrCCmp(arg, "-version:") == 0) { JLI_ReportErrorMessage(SPC_ERROR1); } else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) { @@ -1045,10 +1059,12 @@ } else { if (JLI_StrCmp(arg, "-jar") == 0) jarflag = 1; - if (IsWhiteSpaceOptionArgument(arg) && (argc >= 2)) { - argc--; - argv++; - arg = *argv; + if (IsWhiteSpaceOption(arg)) { + if (has_arg) { + argc--; + argv++; + arg = *argv; + } } /* @@ -1140,6 +1156,108 @@ } /* + * Test if the current argv is an option, i.e. with a leading `-` + * and followed with an argument without a leading `-`. + */ +static jboolean +IsOptionWithArgument(int argc, char** argv) { + char* option; + char* arg; + + if (argc <= 1) + return JNI_FALSE; + + option = *argv; + arg = *(argv+1); + return *option == '-' && *arg != '-'; +} + +/* + * Gets the option, and its argument if the option has an argument. + * It will update *pargc, **pargv to the next option. + */ +static int +GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) { + int argc = *pargc; + char** argv = *pargv; + char* arg = *argv; + + char* option = arg; + char* value = NULL; + char* equals = NULL; + int kind = LAUNCHER_OPTION; + jboolean has_arg = JNI_FALSE; + + // check if this option may be a white-space option with an argument + has_arg = IsOptionWithArgument(argc, argv); + + argv++; --argc; + if (IsLauncherOption(arg)) { + if (has_arg) { + value = *argv; + argv++; --argc; + } + kind = IsLauncherMainOption(arg) ? LAUNCHER_MAIN_OPTION + : LAUNCHER_OPTION_WITH_ARGUMENT; + } else if (IsModuleOption(arg)) { + kind = VM_LONG_OPTION_WITH_ARGUMENT; + if (has_arg) { + value = *argv; + argv++; --argc; + } + + /* + * Support short form alias + */ + if (JLI_StrCmp(arg, "-p") == 0) { + option = "--module-path"; + } + + } else if (JLI_StrCCmp(arg, "--") == 0 && (equals = JLI_StrChr(arg, '=')) != NULL) { + value = equals+1; + if (JLI_StrCCmp(arg, "--list-modules=") == 0 || + JLI_StrCCmp(arg, "--module=") == 0 || + JLI_StrCCmp(arg, "--class-path=") == 0) { + kind = LAUNCHER_OPTION_WITH_ARGUMENT; + } else { + kind = VM_LONG_OPTION; + } + } + +#ifndef OLD_MODULE_OPTIONS + // for transition to support both old and new syntax + if (JLI_StrCmp(arg, "-modulepath") == 0 || + JLI_StrCmp(arg, "-mp") == 0) { + option = "--module-path"; + } else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) { + option = "--upgrade-module-path"; + } else if (JLI_StrCmp(arg, "-addmods") == 0) { + option = "--add-modules"; + } else if (JLI_StrCmp(arg, "-limitmods") == 0) { + option = "--limit-modules"; + } else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) { + option = "--add-exports"; + value = arg + 13; + kind = VM_LONG_OPTION_WITH_ARGUMENT; + } else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) { + option = "--add-reads"; + value = arg + 11; + kind = VM_LONG_OPTION_WITH_ARGUMENT; + } else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) { + option = "--patch-module"; + value = arg + 8; + kind = VM_LONG_OPTION_WITH_ARGUMENT; + } +#endif + + *pargc = argc; + *pargv = argv; + *poption = option; + *pvalue = value; + return kind; +} + +/* * Parses command line arguments. Returns JNI_FALSE if launcher * should exit without starting vm, returns JNI_TRUE if vm needs * to be started to process given options. *pret (the launcher @@ -1158,52 +1276,85 @@ *pret = 0; while ((arg = *argv) != 0 && *arg == '-') { - argv++; --argc; - if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { - ARG_CHECK (argc, ARG_ERROR1, arg); - SetClassPath(*argv); - mode = LM_CLASS; - argv++; --argc; - } else if (JLI_StrCmp(arg, "-modulepath") == 0 || JLI_StrCmp(arg, "-mp") == 0) { - ARG_CHECK (argc, ARG_ERROR4, arg); - SetModulePath(*argv); - argv++; --argc; - } else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) { - ARG_CHECK (argc, ARG_ERROR4, arg); - SetUpgradeModulePath(*argv); - argv++; --argc; - } else if (JLI_StrCmp(arg, "-jar") == 0) { - ARG_CHECK (argc, ARG_ERROR2, arg); + char *option = NULL; + char *value = NULL; + int kind = GetOpt(&argc, &argv, &option, &value); + jboolean has_arg = value != NULL; + +/* + * Option to set main entry point + */ + if (JLI_StrCmp(arg, "-jar") == 0) { + ARG_CHECK(argc, ARG_ERROR2, arg); mode = LM_JAR; - } else if (JLI_StrCmp(arg, "-m") == 0) { - ARG_CHECK (argc, ARG_ERROR5, arg); - SetMainModule(*argv); + } else if (JLI_StrCmp(arg, "--module") == 0 || + JLI_StrCCmp(arg, "--module=") == 0 || + JLI_StrCmp(arg, "-m") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR5, arg); + SetMainModule(value); mode = LM_MODULE; - } else if (JLI_StrCmp(arg, "-addmods") == 0) { - ARG_CHECK (argc, ARG_ERROR6, arg); - SetAddModulesProp(*argv); - argv++; --argc; - } else if (JLI_StrCmp(arg, "-limitmods") == 0) { - ARG_CHECK (argc, ARG_ERROR6, arg); - SetLimitModulesProp(*argv); - argv++; --argc; - } else if (JLI_StrCmp(arg, "-listmods") == 0 || - JLI_StrCCmp(arg, "-listmods:") == 0) { + if (has_arg) { + *pwhat = value; + break; + } + } else if (JLI_StrCmp(arg, "--class-path") == 0 || + JLI_StrCCmp(arg, "--class-path=") == 0 || + JLI_StrCmp(arg, "-classpath") == 0 || + JLI_StrCmp(arg, "-cp") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR1, arg); + SetClassPath(value); + mode = LM_CLASS; + } else if (JLI_StrCmp(arg, "--list-modules") == 0 || + JLI_StrCCmp(arg, "--list-modules=") == 0) { listModules = arg; + + // set listModules to --list-modules= if argument is specified + if (JLI_StrCmp(arg, "--list-modules") == 0 && has_arg) { + static const char format[] = "%s=%s"; + size_t buflen = JLI_StrLen(option) + 2 + JLI_StrLen(value); + listModules = JLI_MemAlloc(buflen); + JLI_Snprintf(listModules, buflen, format, option, value); + } return JNI_TRUE; - } else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) { - static jint n; - char *value = arg + 11; - SetAddReadsProp(n++, value); - } else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) { - static jint n; - char *value = arg + 13; - SetAddExportsProp(n++, value); - } else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) { - static jint n; - char *value = arg + 8; - SetPatchProp(n++, value); - } else if (JLI_StrCmp(arg, "-help") == 0 || +/* + * Parse white-space options + */ + } else if (has_arg) { + if (kind == VM_LONG_OPTION) { + AddOption(option, NULL); + } else if (kind == VM_LONG_OPTION_WITH_ARGUMENT) { + AddLongFormOption(option, value); + } +/* + * Error missing argument + */ + } else if (!has_arg && IsWhiteSpaceOption(arg)) { + if (JLI_StrCmp(arg, "--module-path") == 0 || + JLI_StrCmp(arg, "-p") == 0 || + JLI_StrCmp(arg, "--upgrade-module-path") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR4, arg); + } else if (JLI_StrCmp(arg, "--add-modules") == 0 || + JLI_StrCmp(arg, "--limit-modules") == 0 || + JLI_StrCmp(arg, "--add-exports") == 0 || + JLI_StrCmp(arg, "--add-reads") == 0 || + JLI_StrCmp(arg, "--patch-module") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR6, arg); + } +#ifndef OLD_MODULE_OPTIONS + else if (JLI_StrCmp(arg, "-modulepath") == 0 || + JLI_StrCmp(arg, "-mp") == 0 || + JLI_StrCmp(arg, "-upgrademodulepath") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR4, arg); + } else if (JLI_StrCmp(arg, "-addmods") == 0 || + JLI_StrCmp(arg, "-limitmods") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR6, arg); + } +#endif +/* + * The following cases will cause the argument parsing to stop + */ + } else if (JLI_StrCmp(arg, "--help") == 0 || + JLI_StrCmp(arg, "-help") == 0 || JLI_StrCmp(arg, "-h") == 0 || JLI_StrCmp(arg, "-?") == 0) { printUsage = JNI_TRUE; @@ -1282,7 +1433,7 @@ } } - if (--argc >= 0) { + if (*pwhat == NULL && --argc >= 0) { *pwhat = *argv++; } @@ -1692,7 +1843,7 @@ ListModules(JNIEnv *env, char *optString) { jmethodID listModulesID; - jstring joptString; + jstring joptString = NULL; jclass cls = GetLauncherHelperClass(env); NULL_CHECK(cls); NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,