Dave
Dave

Reputation: 7603

Parsing a command-line into an argv array

I am writing a C++ function on Linux which uses execvp. The only parameter passed to this function is a char* which indicates the arguments for exec. I need to convert this char* to a char** for execvp and I need to take into account quotations, here is an example:

/path/to/program "argument one" argument two
  - results in -
/path/to/program
argument one
argument
two

Is there some built-in method for doing this? if not, is there something simpler I can do short of writing my own parser?

Upvotes: 0

Views: 378

Answers (1)

Alex
Alex

Reputation: 709

#include <string>
#include <vector>

std::vector<std::string> stringToArgv(std::string const& in)
{
    std::vector<std::string> out;

    std::string arg;

    char quoteChar = 0;

    for (std::string::const_iterator I = in.begin(), E = in.end(); I != E; ++I)
    {
        char ch = *I;

        // Quoting a single character using the backslash?
        if (quoteChar == '\\')
        {
            arg.push_back(ch);
            quoteChar = 0;
            continue;
        }

        // Currently quoting using ' or " ?
        if (quoteChar && ch != quoteChar)
        {
            arg.push_back(ch);
            continue;
        }

        switch (ch)
        {
        case '\'': // Toggle quoting
        case '\"': // Toggle weak quoting
        case '\\': // Toggle single character quoting...
            quoteChar = quoteChar ? 0 : ch;
            break;

        case ' ':
        case '\t':
        case '\n':
            // Arguments are separated by whitespace
            if (!arg.empty())
            {
                out.push_back(arg);
                arg.clear();
            }
            break;

        default:
            arg.push_back(ch);
            break;
        }
    }

    // Append the last argument - if any
    if (!arg.empty())
    {
        out.push_back(arg);
    }

    return out;
}

Upvotes: 1

Related Questions