From c48ef2ae36e2169872a828a5399ccd1993837915 Mon Sep 17 00:00:00 2001 From: Brian Gaeke Date: Fri, 15 Aug 2003 21:05:57 +0000 Subject: [PATCH] lib/Support/CommandLine.cpp: Many changes suggested by Chris. It's okay, I'll recover from the emotional damage...maybe someday. :-) Collapse ParseCStringVector into ParseStringVector. Comment it. Make it take a const input. Use std::string::npos instead of -1 (what a mouthful!) Make ParseEnvironmentOptions take const inputs. Check its args at the very beginning. Strdup all the contents of newArgv and free them all at the end. include/Support/CommandLine.h: Constify progName and envVar arguments to ParseEnvironmentOptions(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7905 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/Support/CommandLine.h | 2 +- include/llvm/Support/CommandLine.h | 2 +- lib/Support/CommandLine.cpp | 97 +++++++++++++++-------------- support/lib/Support/CommandLine.cpp | 97 +++++++++++++++-------------- 4 files changed, 104 insertions(+), 94 deletions(-) diff --git a/include/Support/CommandLine.h b/include/Support/CommandLine.h index 5febbcf1c9b..410361797a5 100644 --- a/include/Support/CommandLine.h +++ b/include/Support/CommandLine.h @@ -35,7 +35,7 @@ void ParseCommandLineOptions(int &argc, char **argv, // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // -void ParseEnvironmentOptions(char *progName, char *envvar, +void ParseEnvironmentOptions(const char *progName, const char *envvar, const char *Overview = 0); //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 5febbcf1c9b..410361797a5 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -35,7 +35,7 @@ void ParseCommandLineOptions(int &argc, char **argv, // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // -void ParseEnvironmentOptions(char *progName, char *envvar, +void ParseEnvironmentOptions(const char *progName, const char *envvar, const char *Overview = 0); //===----------------------------------------------------------------------===// diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index f038d39154a..e9793d692ad 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -152,44 +152,48 @@ static bool EatsUnboundedNumberOfValues(const Option *O) { O->getNumOccurrencesFlag() == cl::OneOrMore; } -/// ParseStringVector - Break INPUT up wherever one or more characters -/// from DELIMS are found, and store the resulting tokens in OUTPUT. +/// ParseCStringVector - Break INPUT up wherever one or more +/// whitespace characters are found, and store the resulting tokens in +/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated +/// using strdup (), so it is the caller's responsibility to free () +/// them later. /// -static void ParseStringVector (std::vector &output, - std::string &input, const char *delims) { +static void ParseCStringVector (std::vector &output, + const char *input) { + // Characters which will be treated as token separators: + static const char *delims = " \v\f\t\r\n"; + std::string work (input); - int pos = work.find_first_not_of (delims); - if (pos == -1) return; + // Skip past any delims at head of input string. + size_t pos = work.find_first_not_of (delims); + // If the string consists entirely of delims, then exit early. + if (pos == std::string::npos) return; + // Otherwise, jump forward to beginning of first word. work = work.substr (pos); + // Find position of first delimiter. pos = work.find_first_of (delims); - while (!work.empty() && pos != -1) { - if (pos == -1) break; - output.push_back (work.substr (0,pos)); - int nextpos = work.find_first_not_of (delims, pos + 1); - if (nextpos != -1) { + + while (!work.empty() && pos != std::string::npos) { + // Everything from 0 to POS is the next word to copy. + output.push_back (strdup (work.substr (0,pos).c_str ())); + // Is there another word in the string? + size_t nextpos = work.find_first_not_of (delims, pos + 1); + if (nextpos != std::string::npos) { + // Yes? Then remove delims from beginning ... work = work.substr (work.find_first_not_of (delims, pos + 1)); + // and find the end of the word. pos = work.find_first_of (delims); } else { + // No? (Remainder of string is delims.) End the loop. work = ""; - pos = -1; + pos = std::string::npos; } } - if (!work.empty ()) { - output.push_back (work); - } -} -/// ParseCStringVector - Same effect as ParseStringVector, but the -/// resulting output vector contains dynamically-allocated pointers to -/// char, instead of standard C++ strings. -/// -static void ParseCStringVector (std::vector &output, - std::string &input, const char *delims) { - std::vector work; - ParseStringVector (work, input, delims); - for (std::vector::iterator i = work.begin(), e = work.end(); - i != e; ++i) { - output.push_back (strdup (i->c_str ())); + // If `input' ended with non-delim char, then we'll get here with + // the last word of `input' in `work'; copy it now. + if (!work.empty ()) { + output.push_back (strdup (work.c_str ())); } } @@ -198,32 +202,33 @@ static void ParseCStringVector (std::vector &output, /// from the caller (as PROGNAME) and its command-line arguments from /// an environment variable (whose name is given in ENVVAR). /// -void cl::ParseEnvironmentOptions (char *progName, char *envvar, +void cl::ParseEnvironmentOptions (const char *progName, const char *envVar, const char *Overview) { - // Get program's "name", which we wouldn't know without the caller - // telling us. + // Check args. assert (progName && "Program name not specified"); - static std::vector newargv; // Maybe making it "static" is a hack. - int newargc; - newargv.push_back (progName); - + assert (envVar && "Environment variable name missing"); + // Get the environment variable they want us to parse options out of. - assert (envvar && "Environment variable name missing"); - char *envvalue = getenv (envvar); - if (envvalue == NULL) { - // Env var not set --> act like there are no more command line - // arguments. - newargc = newargv.size (); - ParseCommandLineOptions (newargc, &newargv[0], Overview); + const char *envValue = getenv (envVar); + if (!envValue) return; - } - std::string envvaluestr (envvalue); + + // Get program's "name", which we wouldn't know without the caller + // telling us. + std::vector newArgv; + newArgv.push_back (strdup (progName)); // Parse the value of the environment variable into a "command line" // and hand it off to ParseCommandLineOptions(). - ParseCStringVector (newargv, envvaluestr, " \v\f\t\r\n"); - newargc = newargv.size (); - ParseCommandLineOptions (newargc, &newargv[0], Overview); + ParseCStringVector (newArgv, envValue); + int newArgc = newArgv.size (); + ParseCommandLineOptions (newArgc, &newArgv[0], Overview); + + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin (), e = newArgv.end (); + i != e; ++i) { + free (*i); + } } void cl::ParseCommandLineOptions(int &argc, char **argv, diff --git a/support/lib/Support/CommandLine.cpp b/support/lib/Support/CommandLine.cpp index f038d39154a..e9793d692ad 100644 --- a/support/lib/Support/CommandLine.cpp +++ b/support/lib/Support/CommandLine.cpp @@ -152,44 +152,48 @@ static bool EatsUnboundedNumberOfValues(const Option *O) { O->getNumOccurrencesFlag() == cl::OneOrMore; } -/// ParseStringVector - Break INPUT up wherever one or more characters -/// from DELIMS are found, and store the resulting tokens in OUTPUT. +/// ParseCStringVector - Break INPUT up wherever one or more +/// whitespace characters are found, and store the resulting tokens in +/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated +/// using strdup (), so it is the caller's responsibility to free () +/// them later. /// -static void ParseStringVector (std::vector &output, - std::string &input, const char *delims) { +static void ParseCStringVector (std::vector &output, + const char *input) { + // Characters which will be treated as token separators: + static const char *delims = " \v\f\t\r\n"; + std::string work (input); - int pos = work.find_first_not_of (delims); - if (pos == -1) return; + // Skip past any delims at head of input string. + size_t pos = work.find_first_not_of (delims); + // If the string consists entirely of delims, then exit early. + if (pos == std::string::npos) return; + // Otherwise, jump forward to beginning of first word. work = work.substr (pos); + // Find position of first delimiter. pos = work.find_first_of (delims); - while (!work.empty() && pos != -1) { - if (pos == -1) break; - output.push_back (work.substr (0,pos)); - int nextpos = work.find_first_not_of (delims, pos + 1); - if (nextpos != -1) { + + while (!work.empty() && pos != std::string::npos) { + // Everything from 0 to POS is the next word to copy. + output.push_back (strdup (work.substr (0,pos).c_str ())); + // Is there another word in the string? + size_t nextpos = work.find_first_not_of (delims, pos + 1); + if (nextpos != std::string::npos) { + // Yes? Then remove delims from beginning ... work = work.substr (work.find_first_not_of (delims, pos + 1)); + // and find the end of the word. pos = work.find_first_of (delims); } else { + // No? (Remainder of string is delims.) End the loop. work = ""; - pos = -1; + pos = std::string::npos; } } - if (!work.empty ()) { - output.push_back (work); - } -} -/// ParseCStringVector - Same effect as ParseStringVector, but the -/// resulting output vector contains dynamically-allocated pointers to -/// char, instead of standard C++ strings. -/// -static void ParseCStringVector (std::vector &output, - std::string &input, const char *delims) { - std::vector work; - ParseStringVector (work, input, delims); - for (std::vector::iterator i = work.begin(), e = work.end(); - i != e; ++i) { - output.push_back (strdup (i->c_str ())); + // If `input' ended with non-delim char, then we'll get here with + // the last word of `input' in `work'; copy it now. + if (!work.empty ()) { + output.push_back (strdup (work.c_str ())); } } @@ -198,32 +202,33 @@ static void ParseCStringVector (std::vector &output, /// from the caller (as PROGNAME) and its command-line arguments from /// an environment variable (whose name is given in ENVVAR). /// -void cl::ParseEnvironmentOptions (char *progName, char *envvar, +void cl::ParseEnvironmentOptions (const char *progName, const char *envVar, const char *Overview) { - // Get program's "name", which we wouldn't know without the caller - // telling us. + // Check args. assert (progName && "Program name not specified"); - static std::vector newargv; // Maybe making it "static" is a hack. - int newargc; - newargv.push_back (progName); - + assert (envVar && "Environment variable name missing"); + // Get the environment variable they want us to parse options out of. - assert (envvar && "Environment variable name missing"); - char *envvalue = getenv (envvar); - if (envvalue == NULL) { - // Env var not set --> act like there are no more command line - // arguments. - newargc = newargv.size (); - ParseCommandLineOptions (newargc, &newargv[0], Overview); + const char *envValue = getenv (envVar); + if (!envValue) return; - } - std::string envvaluestr (envvalue); + + // Get program's "name", which we wouldn't know without the caller + // telling us. + std::vector newArgv; + newArgv.push_back (strdup (progName)); // Parse the value of the environment variable into a "command line" // and hand it off to ParseCommandLineOptions(). - ParseCStringVector (newargv, envvaluestr, " \v\f\t\r\n"); - newargc = newargv.size (); - ParseCommandLineOptions (newargc, &newargv[0], Overview); + ParseCStringVector (newArgv, envValue); + int newArgc = newArgv.size (); + ParseCommandLineOptions (newArgc, &newArgv[0], Overview); + + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin (), e = newArgv.end (); + i != e; ++i) { + free (*i); + } } void cl::ParseCommandLineOptions(int &argc, char **argv, -- 2.34.1