Improved argument parsing logic used by the REPL

It now handles quoted strings, although it doesn't understand escape
sequences yet.
This commit is contained in:
John Wiegley 2009-10-26 17:17:01 -04:00
parent 92d1bbbe75
commit feff681f44
3 changed files with 55 additions and 15 deletions

View file

@ -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;

View file

@ -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

View file

@ -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())
/*@}*/