< prev index next >

src/java.base/share/native/libjli/args.c

Print this page

        

@@ -77,10 +77,15 @@
 // Initialize to 1, as the first argument is the app name and not preprocessed
 static size_t argsCount = 1;
 static jboolean stopExpansion = JNI_FALSE;
 static jboolean relaunch = JNI_FALSE;
 
+/*
+ * Prototypes for internal functions.
+ */
+static jboolean expand(JLI_List args, const char *str, const char *var_name);
+
 JNIEXPORT void JNICALL
 JLI_InitArgProcessing(jboolean hasJavaArgs, jboolean disableArgFile) {
     // No expansion for relaunch
     if (argsCount != 1) {
         relaunch = JNI_TRUE;

@@ -374,13 +379,26 @@
     }
 
     return rv;
 }
 
+/*
+ * expand a string into a list of words separated by whitespace.
+ */
+static JLI_List expandArg(const char *arg) {
+    JLI_List rv;
+
+    /* arbitrarily pick 8, seems to be a reasonable number of arguments */
+    rv = JLI_List_new(8);
+
+    expand(rv, arg, NULL);
+
+    return rv;
+}
+
 JNIEXPORT JLI_List JNICALL
-JLI_PreprocessArg(const char *arg)
-{
+JLI_PreprocessArg(const char *arg, jboolean expandSourceOpt) {
     JLI_List rv;
 
     if (firstAppArgIndex > 0) {
         // In user application arg, no more work.
         return NULL;

@@ -390,10 +408,16 @@
         // still looking for user application arg
         checkArg(arg);
         return NULL;
     }
 
+    if (expandSourceOpt
+            && JLI_StrCCmp(arg, "--source") == 0
+            && JLI_StrChr(arg, ' ') != NULL) {
+        return expandArg(arg);
+    }
+
     if (arg[0] != '@') {
         checkArg(arg);
         return NULL;
     }
 

@@ -433,13 +457,10 @@
 }
 
 JNIEXPORT jboolean JNICALL
 JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) {
     char *env = getenv(var_name);
-    char *p, *arg;
-    char quote;
-    JLI_List argsInFile;
 
     if (firstAppArgIndex == 0) {
         // Not 'java', return
         return JNI_FALSE;
     }

@@ -451,59 +472,83 @@
     if (NULL == env) {
         return JNI_FALSE;
     }
 
     JLI_ReportMessage(ARG_INFO_ENVVAR, var_name, env);
+    return expand(args, env, var_name);
+}
+
+/*
+ * Expand a string into a list of args.
+ * If the string is the result of looking up an environment variable,
+ * var_name should be set to the name of that environment variable,
+ * for use if needed in error messages.
+ */
+
+static jboolean expand(JLI_List args, const char *str, const char *var_name) {
+    jboolean inEnvVar = (var_name != NULL);
+
+    char *p, *arg;
+    char quote;
+    JLI_List argsInFile;
 
     // This is retained until the process terminates as it is saved as the args
-    p = JLI_MemAlloc(JLI_StrLen(env) + 1);
-    while (*env != '\0') {
-        while (*env != '\0' && isspace(*env)) {
-            env++;
+    p = JLI_MemAlloc(JLI_StrLen(str) + 1);
+    while (*str != '\0') {
+        while (*str != '\0' && isspace(*str)) {
+            str++;
         }
 
         // Trailing space
-        if (*env == '\0') {
+        if (*str == '\0') {
             break;
         }
 
         arg = p;
-        while (*env != '\0' && !isspace(*env)) {
-            if (*env == '"' || *env == '\'') {
-                quote = *env++;
-                while (*env != quote && *env != '\0') {
-                    *p++ = *env++;
+        while (*str != '\0' && !isspace(*str)) {
+            if (inEnvVar && (*str == '"' || *str == '\'')) {
+                quote = *str++;
+                while (*str != quote && *str != '\0') {
+                    *p++ = *str++;
                 }
 
-                if (*env == '\0') {
+                if (*str == '\0') {
                     JLI_ReportMessage(ARG_ERROR8, var_name);
                     exit(1);
                 }
-                env++;
+                str++;
             } else {
-                *p++ = *env++;
+                *p++ = *str++;
             }
         }
 
         *p++ = '\0';
 
-        argsInFile = JLI_PreprocessArg(arg);
+        argsInFile = JLI_PreprocessArg(arg, JNI_FALSE);
 
         if (NULL == argsInFile) {
             if (isTerminalOpt(arg)) {
+                if (inEnvVar) {
                 JLI_ReportMessage(ARG_ERROR9, arg, var_name);
+                } else {
+                    JLI_ReportMessage(ARG_ERROR15, arg);
+                }
                 exit(1);
             }
             JLI_List_add(args, arg);
         } else {
             size_t cnt, idx;
             char *argFile = arg;
             cnt = argsInFile->size;
             for (idx = 0; idx < cnt; idx++) {
                 arg = argsInFile->elements[idx];
                 if (isTerminalOpt(arg)) {
+                    if (inEnvVar) {
                     JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name);
+                    } else {
+                        JLI_ReportMessage(ARG_ERROR16, arg, argFile);
+                    }
                     exit(1);
                 }
                 JLI_List_add(args, arg);
             }
             // Shallow free, we reuse the string to avoid copy

@@ -515,15 +560,19 @@
          * must always appear after expansion, as a main-class could be specified
          * indirectly into environment variable via an @argfile, and it must be
          * caught now.
          */
         if (firstAppArgIndex != NOT_FOUND) {
+            if (inEnvVar) {
             JLI_ReportMessage(ARG_ERROR11, var_name);
+            } else {
+                JLI_ReportMessage(ARG_ERROR17);
+            }
             exit(1);
         }
 
-        assert (*env == '\0' || isspace(*env));
+        assert (*str == '\0' || isspace(*str));
     }
 
     return JNI_TRUE;
 }
 

@@ -640,11 +689,11 @@
         "c:\\partial quote\\lib" };
     DO_CASE(escape_quote);
 
     if (argc > 1) {
         for (i = 0; i < argc; i++) {
-            JLI_List tokens = JLI_PreprocessArg(argv[i]);
+            JLI_List tokens = JLI_PreprocessArg(argv[i], JNI_FALSE);
             if (NULL != tokens) {
                 for (j = 0; j < tokens->size; j++) {
                     printf("Token[%lu]: <%s>\n", (unsigned long) j, tokens->elements[j]);
                 }
             }
< prev index next >