diff options
-rw-r--r-- | src/main.cc | 15 | ||||
-rw-r--r-- | src/utils.cc | 53 | ||||
-rw-r--r-- | src/utils.h | 2 |
3 files changed, 55 insertions, 15 deletions
diff --git a/src/main.cc b/src/main.cc index c9a922af..9f0e8690 100644 --- a/src/main.cc +++ b/src/main.cc @@ -37,21 +37,6 @@ using namespace ledger; -namespace { - strings_list split_arguments(char * line) - { - strings_list args; - - // jww (2009-02-04): This is too naive - for (char * p = std::strtok(line, " \t"); - p; - p = std::strtok(NULL, " \t")) - args.push_back(p); - - return args; - } -} - #ifdef HAVE_BOOST_PYTHON namespace ledger { extern char * argv0; diff --git a/src/utils.cc b/src/utils.cc index 0afea4c2..85a7aa46 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -442,6 +442,59 @@ string::~string() throw() { ledger::string empty_string(""); +ledger::strings_list split_arguments(const char * line) +{ + using namespace ledger; + + strings_list args; + + char buf[4096]; + char * q = buf; + char in_quoted_string = '\0'; + + for (const char * p = line; *p; p++) { + if (! in_quoted_string && std::isspace(*p)) { + if (q != buf) { + *q = '\0'; + args.push_back(buf); + q = buf; + } + } + else if (in_quoted_string != '\'' && *p == '\\') { + p++; + if (! *p) + throw_(std::logic_error, _("Invalid use of backslash")); + *q++ = *p; + } + else if (in_quoted_string != '"' && *p == '\'') { + if (in_quoted_string == '\'') + in_quoted_string = '\0'; + else + in_quoted_string = '\''; + } + else if (in_quoted_string != '\'' && *p == '"') { + if (in_quoted_string == '"') + in_quoted_string = '\0'; + else + in_quoted_string = '"'; + } + else { + *q++ = *p; + } + } + + if (in_quoted_string) + throw_(std::logic_error, + _("Unterminated string, expected '%1'") << in_quoted_string); + + if (q != buf) { + *q = '\0'; + args.push_back(buf); + } + + return args; +} + /********************************************************************** * * Logging diff --git a/src/utils.h b/src/utils.h index 7f5ca017..98bdf9af 100644 --- a/src/utils.h +++ b/src/utils.h @@ -237,6 +237,8 @@ inline bool operator!=(const string& __lhs, const char* __rhs) extern ledger::string empty_string; +ledger::strings_list split_arguments(const char * line); + #define IF_VERIFY() if (DO_VERIFY()) /*@}*/ |