=== modified file 'lisp/subr.el' --- lisp/subr.el 2011-04-19 13:44:55 +0000 +++ lisp/subr.el 2011-04-25 02:05:07 +0000 @@ -2507,19 +2507,33 @@ "Quote ARGUMENT for passing as argument to an inferior shell." (if (or (eq system-type 'ms-dos) (and (eq system-type 'windows-nt) (w32-shell-dos-semantics))) - ;; Quote using double quotes, but escape any existing quotes in - ;; the argument with backslashes. - (let ((result "") - (start 0) - end) - (if (or (null (string-match "[^\"]" argument)) - (< (match-end 0) (length argument))) - (while (string-match "[\"]" argument start) - (setq end (match-beginning 0) - result (concat result (substring argument start end) - "\\" (substring argument end (1+ end))) - start (1+ end)))) - (concat "\"" result (substring argument start) "\"")) + + ;; First, quote argument so that CommandLineToArgvW will + ;; understand it. Inside an argument, 2n or 2n + 1 backslashes + ;; followed by a double quote produces n backslashes. In the + ;; former case, we also ends the argument. In the latter case, + ;; we also produce a double-quote character and end the + ;; argument. Backslashes not followed by a quotation mark are + ;; left alone. See + ;; http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx + ;; After we perform that level of quoting, replace shell + ;; metacharacters so that cmd won't mangle our argument. + + (replace-regexp-in-string + "\\([()\"<>&|^]\\)" + "^\\1" + (concat + "\"" + ;; escape backslashes at end of string + (replace-regexp-in-string + "\\(\\\\*\\)$" + "\\1\\1" + ;; escape backslashes and quotes in string body + (replace-regexp-in-string + "\\(\\\\*\\)\"" + "\\1\\1\\\\\"" + argument)) + "\"")) (if (equal argument "") "''" ;; Quote everything except POSIX filename characters.