| 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 | #ifdef _WIN32 | 
|---|
| 11 | namespace boost { namespace program_options { | 
|---|
| 12 |  | 
|---|
| 13 |     using namespace std; | 
|---|
| 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 | 
|---|
| 22 |     std::vector<std::string> split_winmain(const std::string& input) | 
|---|
| 23 |     { | 
|---|
| 24 |         std::vector<std::string> result; | 
|---|
| 25 |  | 
|---|
| 26 |         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 |             int backslash_count = 0; | 
|---|
| 36 |              | 
|---|
| 37 |             for(; i != e; ++i) { | 
|---|
| 38 |                 if (*i == '"') { | 
|---|
| 39 |                     // '"' preceded by even number (n) of backslashes generates | 
|---|
| 40 |                     // n/2 backslashes and is a quoted block delimiter | 
|---|
| 41 |                     if (backslash_count % 2 == 0) { | 
|---|
| 42 |                         current.append(backslash_count / 2, '\\'); | 
|---|
| 43 |                         inside_quoted = !inside_quoted; | 
|---|
| 44 |                         // '"' preceded by odd number (n) of backslashes generates | 
|---|
| 45 |                         // (n-1)/2 backslashes and is literal quote. | 
|---|
| 46 |                     } else { | 
|---|
| 47 |                         current.append(backslash_count / 2, '\\');                 | 
|---|
| 48 |                         current += '"';                 | 
|---|
| 49 |                     } | 
|---|
| 50 |                     backslash_count = 0; | 
|---|
| 51 |                 } else if (*i == '\\') { | 
|---|
| 52 |                     ++backslash_count; | 
|---|
| 53 |                 } else { | 
|---|
| 54 |                     // Not quote or backslash. All accumulated backslashes should be | 
|---|
| 55 |                     // added | 
|---|
| 56 |                     if (backslash_count) { | 
|---|
| 57 |                         current.append(backslash_count, '\\'); | 
|---|
| 58 |                         backslash_count = 0; | 
|---|
| 59 |                     } | 
|---|
| 60 |                     if (isspace((unsigned char)*i) && !inside_quoted) { | 
|---|
| 61 |                         // Space outside quoted section terminate the current argument | 
|---|
| 62 |                         result.push_back(current); | 
|---|
| 63 |                         current.resize(0); | 
|---|
| 64 |                         for(;i != e && isspace((unsigned char)*i); ++i) | 
|---|
| 65 |                             ; | 
|---|
| 66 |                         --i; | 
|---|
| 67 |                     } else {                   | 
|---|
| 68 |                         current += *i; | 
|---|
| 69 |                     } | 
|---|
| 70 |                 } | 
|---|
| 71 |             } | 
|---|
| 72 |  | 
|---|
| 73 |             // If we have trailing backslashes, add them | 
|---|
| 74 |             if (backslash_count) | 
|---|
| 75 |                 current.append(backslash_count, '\\'); | 
|---|
| 76 |          | 
|---|
| 77 |             // If we have non-empty 'current' or we're still in quoted | 
|---|
| 78 |             // section (even if 'current' is empty), add the last token. | 
|---|
| 79 |             if (!current.empty() || inside_quoted) | 
|---|
| 80 |                 result.push_back(current);         | 
|---|
| 81 |         } | 
|---|
| 82 |         return result; | 
|---|
| 83 |     } | 
|---|
| 84 |  | 
|---|
| 85 | #ifndef BOOST_NO_STD_WSTRING | 
|---|
| 86 |     BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> | 
|---|
| 87 |     split_winmain(const std::wstring& cmdline) | 
|---|
| 88 |     { | 
|---|
| 89 |         vector<wstring> result; | 
|---|
| 90 |         vector<string> aux = split_winmain(to_internal(cmdline)); | 
|---|
| 91 |         for (unsigned i = 0, e = aux.size(); i < e; ++i) | 
|---|
| 92 |             result.push_back(from_utf8(aux[i])); | 
|---|
| 93 |         return result;         | 
|---|
| 94 |     } | 
|---|
| 95 | #endif | 
|---|
| 96 |  | 
|---|
| 97 | }} | 
|---|
| 98 | #endif | 
|---|