jdk/src/java.base/share/native/libjli/java.c
changeset 40261 86a49ba76f52
parent 39345 344e8211e184
child 40680 01c426b7cb59
--- a/jdk/src/java.base/share/native/libjli/java.c	Wed Aug 10 22:48:25 2016 +0100
+++ b/jdk/src/java.base/share/native/libjli/java.c	Wed Aug 10 15:51:25 2016 -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=<module-names> 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,