• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Vladimir Prus 2002-2004.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt
4 // or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #define BOOST_PROGRAM_OPTIONS_SOURCE
7 #include <boost/program_options/parsers.hpp>
8 #include <cctype>
9 
10 using std::size_t;
11 
12 #ifdef _WIN32
13 namespace boost { namespace program_options {
14 
15     // Take a command line string and splits in into tokens, according
16     // to the rules windows command line processor uses.
17     //
18     // The rules are pretty funny, see
19     //    http://article.gmane.org/gmane.comp.lib.boost.user/3005
20     //    http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
21     BOOST_PROGRAM_OPTIONS_DECL
split_winmain(const std::string & input)22     std::vector<std::string> split_winmain(const std::string& input)
23     {
24         std::vector<std::string> result;
25 
26         std::string::const_iterator i = input.begin(), e = input.end();
27         for(;i != e; ++i)
28             if (!isspace((unsigned char)*i))
29                 break;
30 
31         if (i != e) {
32 
33             std::string current;
34             bool inside_quoted = false;
35             bool empty_quote = false;
36             int backslash_count = 0;
37 
38             for(; i != e; ++i) {
39                 if (*i == '"') {
40                     // '"' preceded by even number (n) of backslashes generates
41                     // n/2 backslashes and is a quoted block delimiter
42                     if (backslash_count % 2 == 0) {
43                         current.append(backslash_count / 2, '\\');
44                         empty_quote = inside_quoted && current.empty();
45                         inside_quoted = !inside_quoted;
46                         // '"' preceded by odd number (n) of backslashes generates
47                         // (n-1)/2 backslashes and is literal quote.
48                     } else {
49                         current.append(backslash_count / 2, '\\');
50                         current += '"';
51                     }
52                     backslash_count = 0;
53                 } else if (*i == '\\') {
54                     ++backslash_count;
55                 } else {
56                     // Not quote or backslash. All accumulated backslashes should be
57                     // added
58                     if (backslash_count) {
59                         current.append(backslash_count, '\\');
60                         backslash_count = 0;
61                     }
62                     if (isspace((unsigned char)*i) && !inside_quoted) {
63                         // Space outside quoted section terminate the current argument
64                         result.push_back(current);
65                         current.resize(0);
66                         empty_quote = false;
67                         for(;i != e && isspace((unsigned char)*i); ++i)
68                             ;
69                         --i;
70                     } else {
71                         current += *i;
72                     }
73                 }
74             }
75 
76             // If we have trailing backslashes, add them
77             if (backslash_count)
78                 current.append(backslash_count, '\\');
79 
80             // If we have non-empty 'current' or we're still in quoted
81             // section (even if 'current' is empty), add the last token.
82             if (!current.empty() || inside_quoted || empty_quote)
83                 result.push_back(current);
84         }
85         return result;
86     }
87 
88 #ifndef BOOST_NO_STD_WSTRING
89     BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
split_winmain(const std::wstring & cmdline)90     split_winmain(const std::wstring& cmdline)
91     {
92         std::vector<std::wstring> result;
93         std::vector<std::string> aux = split_winmain(to_internal(cmdline));
94         for (size_t i = 0, e = aux.size(); i < e; ++i)
95             result.push_back(from_utf8(aux[i]));
96         return result;
97     }
98 #endif
99 
100 }}
101 #endif
102 
103