From f27f579358d2c12fc3926bfd5bb95ef3e08ca6a7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 2 Apr 2019 15:09:44 +0200 Subject: Handle combined option values in argv_file_scanner Turns out we cannot just pass them along as combined because of quoting. While at it, also add support for quoting non-option arguments. --- cli/options.cxx | 80 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 34 deletions(-) (limited to 'cli/options.cxx') diff --git a/cli/options.cxx b/cli/options.cxx index 809b588..bb102e0 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -372,45 +372,59 @@ namespace cli if (line.empty () || line[0] == '#') continue; - string::size_type p (line.find (' ')); - - if (p == string::npos) + string::size_type p (string::npos); + if (line.compare (0, 1, "-") == 0) { - if (!skip_) - skip_ = (line == "--"); + p = line.find (' '); - args_.push_back (line); + string::size_type q (line.find ('=')); + if (q != string::npos && q < p) + p = q; } - else + + string s1; + if (p != string::npos) { - string s1 (line, 0, p); + s1.assign (line, 0, p); // Skip leading whitespaces in the argument. // - n = line.size (); - for (++p; p < n; ++p) + if (line[p] == '=') + ++p; + else { - char c (line[p]); - - if (c != ' ' && c != '\t' && c != '\r') - break; + n = line.size (); + for (++p; p < n; ++p) + { + char c (line[p]); + if (c != ' ' && c != '\t' && c != '\r') + break; + } } + } + else if (!skip_) + skip_ = (line == "--"); - string s2 (line, p); + string s2 (line, p != string::npos ? p : 0); - // If the string is wrapped in quotes, remove them. - // - n = s2.size (); - char cf (s2[0]), cl (s2[n - 1]); + // If the string (which is an option value or argument) is + // wrapped in quotes, remove them. + // + n = s2.size (); + char cf (s2[0]), cl (s2[n - 1]); - if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') - { - if (n == 1 || cf != cl) - throw unmatched_quote (s2); + if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') + { + if (n == 1 || cf != cl) + throw unmatched_quote (s2); - s2 = string (s2, 1, n - 2); - } + s2 = string (s2, 1, n - 2); + } + if (!s1.empty ()) + { + // See if this is another file option. + // const option_info* oi; if (!skip_ && (oi = find (s1.c_str ()))) { @@ -420,19 +434,19 @@ namespace cli if (oi->search_func != 0) { std::string f (oi->search_func (s2.c_str (), oi->arg)); - if (!f.empty ()) load (f); } else load (s2); + + continue; } - else - { - args_.push_back (s1); - args_.push_back (s2); - } + + args_.push_back (s1); } + + args_.push_back (s2); } } @@ -1659,9 +1673,7 @@ print_usage (::std::ostream& os, ::cli::usage_para p) << " the list of names that should not be used as" << ::std::endl << " identifiers." << ::std::endl; - os << "--options-file Read additional options from with each" << ::std::endl - << " option appearing on a separate line optionally" << ::std::endl - << " followed by space and an option value." << ::std::endl; + os << "--options-file Read additional options from ." << ::std::endl; p = ::cli::usage_para::option; -- cgit v1.1