+/* Windows command line escaping. Based on
+ * <http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx> and
+ * <http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft%28v=vs.85%29.aspx>.
+ *
+ * The caller is responsible for initializing @buffer; prior contents are lost.
+ */
+static const char *win_escape_arg(const char *to_escape, GString *buffer)
+{
+ size_t backslash_count;
+ const char *c;
+
+ /* open with a double quote */
+ g_string_assign(buffer, "\"");
+
+ backslash_count = 0;
+ for (c = to_escape; *c != '\0'; ++c) {
+ switch (*c) {
+ case '\\':
+ /* The meaning depends on the first non-backslash character coming
+ * up.
+ */
+ ++backslash_count;
+ break;
+
+ case '"':
+ /* We must escape each pending backslash, then escape the double
+ * quote. This creates a case of "odd number of backslashes [...]
+ * followed by a double quotation mark".
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append(buffer, "\\\\");
+ }
+ g_string_append(buffer, "\\\"");
+ break;
+
+ default:
+ /* Any pending backslashes are without special meaning, flush them.
+ * "Backslashes are interpreted literally, unless they immediately
+ * precede a double quotation mark."
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append_c(buffer, '\\');
+ }
+ g_string_append_c(buffer, *c);
+ }
+ }
+
+ /* We're about to close with a double quote in string delimiter role.
+ * Double all pending backslashes, creating a case of "even number of
+ * backslashes [...] followed by a double quotation mark".
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append(buffer, "\\\\");
+ }
+ g_string_append_c(buffer, '"');
+
+ return buffer->str;
+}
+