src/windows/bin/cmdtoargs.c

Print this page
rev 8095 : imported patch 8016110

@@ -51,114 +51,136 @@
 } StdArg ;
 #endif
 static StdArg *stdargs;
 static int    stdargc;
 
+static int copyCh(USHORT ch, char* dest) {
+    if (HIBYTE(ch) == 0) {
+        *dest = (char)ch;
+        return 1;
+    } else {
+        *((USHORT *)dest) = ch;
+        return 2;
+    }
+}
+
 static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) {
 
     char* src = cmdline;
     char* dest = arg;
     jboolean separator = JNI_FALSE;
     int quotes = 0;
     int slashes = 0;
 
-    char prev = 0;
-    char ch = 0;
+    // "prev"/"ch" may contain either a single byte, or a double byte
+    // character encoded in CP_ACP.
+    USHORT prev = 0;
+    USHORT ch = 0;
     int i;
     jboolean done = JNI_FALSE;
+    int charLength;
 
     *wildcard = JNI_FALSE;
-    while ((ch = *src) != 0 && !done) {
+    while (!done) {
+        charLength = CharNextExA(CP_ACP, src, 0) - src;
+        if (charLength == 0) {
+            break;
+        } else if (charLength == 1) {
+            ch = (USHORT)(UCHAR)src[0];
+        } else {
+            ch = ((USHORT *)src)[0];
+        }
+
         switch (ch) {
-        case '"':
+        case L'"':
             if (separator) {
                 done = JNI_TRUE;
                 break;
             }
-            if (prev == '\\') {
+            if (prev == L'\\') {
                 for (i = 1; i < slashes; i += 2) {
-                    *dest++ = prev;
+                    dest += copyCh(prev, dest);
                 }
                 if (slashes % 2 == 1) {
-                    *dest++ = ch;
+                    dest += copyCh(ch, dest);
                 } else {
                     quotes++;
                 }
-            } else if (prev == '"' && quotes % 2 == 0) {
+            } else if (prev == L'"' && quotes % 2 == 0) {
                 quotes++;
-                *dest++ = ch; // emit every other consecutive quote
+                dest += copyCh(ch, dest); // emit every other consecutive quote
             } else if (quotes == 0) {
                 quotes++; // starting quote
             } else {
                 quotes--; // matching quote
             }
             slashes = 0;
             break;
 
-        case '\\':
+        case L'\\':
             slashes++;
             if (separator) {
                 done = JNI_TRUE;
                 separator = JNI_FALSE;
             }
             break;
 
-        case ' ':
-        case '\t':
-            if (prev == '\\') {
+        case L' ':
+        case L'\t':
+            if (prev == L'\\') {
                 for (i = 0 ; i < slashes; i++) {
-                   *dest++ = prev;
+                    dest += copyCh(prev, dest);
                 }
             }
             if (quotes % 2 == 1) {
-                *dest++ = ch;
+                dest += copyCh(ch, dest);
             } else {
                 separator = JNI_TRUE;
             }
             slashes = 0;
             break;
 
-        case '*':
-        case '?':
+        case L'*':
+        case L'?':
             if (separator) {
                 done = JNI_TRUE;
                 separator = JNI_FALSE;
                 break;
             }
             if (quotes % 2 == 0) {
                 *wildcard = JNI_TRUE;
             }
-            if (prev == '\\') {
+            if (prev == L'\\') {
                 for (i = 0 ; i < slashes ; i++) {
-                    *dest++ = prev;
+                    dest += copyCh(prev, dest);
                 }
             }
-            *dest++ = ch;
+            dest += copyCh(ch, dest);
             break;
 
         default:
-            if (prev == '\\') {
+            if (prev == L'\\') {
                 for (i = 0 ; i < slashes ; i++) {
-                   *dest++ = prev;
+                    dest += copyCh(prev, dest);
                 }
-                *dest++ = ch;
+                dest += copyCh(ch, dest);
             } else if (separator) {
                 done = JNI_TRUE;
             } else {
-                *dest++ = ch;
+                dest += copyCh(ch, dest);
             }
             slashes = 0;
         }
 
         if (!done) {
             prev = ch;
-            src++;
+            src += charLength;
         }
     }
-    if (prev == '\\') {
+    if (prev == L'\\') {
         for (i = 0; i < slashes; i++) {
-            *dest++ = prev;
+            dest += copyCh(prev, dest);
         }
     }
     *dest = 0;
     return done ? src : NULL;
 }