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