Factor out OptTable::ParseArgs, for parsing an entire argument vector.

llvm-svn: 89327
This commit is contained in:
Daniel Dunbar 2009-11-19 06:35:06 +00:00
parent 2a6c92fcb6
commit 52ed5feee5
3 changed files with 68 additions and 29 deletions

View File

@ -124,7 +124,7 @@ namespace options {
return getInfo(id).MetaVar;
}
/// parseOneArg - Parse a single argument; returning the new argument and
/// ParseOneArg - Parse a single argument; returning the new argument and
/// updating Index.
///
/// \param [in] [out] Index - The current parsing position in the argument
@ -135,6 +135,27 @@ namespace options {
/// (in which case Index still points at the conceptual next argument string
/// to parse).
Arg *ParseOneArg(const InputArgList &Args, unsigned &Index) const;
/// ParseArgs - Parse an list of arguments into an InputArgList.
///
/// The resulting InputArgList will reference the strings in [ArgBegin,
/// ArgEnd), and their lifetime should extend past that of the returned
/// InputArgList.
///
/// The only error that can occur in this routine is if an argument is
/// missing values; in this case \arg MissingArgCount will be non-zero.
///
/// \param ArgBegin - The beginning of the argument vector.
/// \param ArgEnd - The end of the argument vector.
/// \param MissingArgIndex - On error, the index of the option which could
/// not be parsed.
/// \param MissingArgCount - On error, the number of missing options.
/// \return - An InputArgList; on error this will contain all the options
/// which could be parsed.
InputArgList *ParseArgs(const char **ArgBegin,
const char **ArgEnd,
unsigned &MissingArgIndex,
unsigned &MissingArgCount) const;
};
}
}

View File

@ -76,40 +76,23 @@ Driver::~Driver() {
InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
const char **ArgEnd) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
// FIXME: Handle '@' args (or at least error on them).
unsigned Index = 0, End = ArgEnd - ArgBegin;
while (Index < End) {
// gcc's handling of empty arguments doesn't make sense, but this is not a
// common use case. :)
//
// We just ignore them here (note that other things may still take them as
// arguments).
if (Args->getArgString(Index)[0] == '\0') {
++Index;
continue;
}
unsigned Prev = Index;
Arg *A = getOpts().ParseOneArg(*Args, Index);
assert(Index > Prev && "Parser failed to consume argument.");
unsigned MissingArgIndex, MissingArgCount;
InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd,
MissingArgIndex, MissingArgCount);
// Check for missing argument error.
if (!A) {
assert(Index >= End && "Unexpected parser error.");
if (MissingArgCount)
Diag(clang::diag::err_drv_missing_argument)
<< Args->getArgString(Prev)
<< (Index - Prev - 1);
break;
}
<< Args->getArgString(MissingArgIndex) << MissingArgCount;
// Check for unsupported options.
for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
it != ie; ++it) {
Arg *A = *it;
if (A->getOption().isUnsupported()) {
Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
continue;
}
Args->append(A);
}
return Args;

View File

@ -220,3 +220,38 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
return new PositionalArg(TheUnknownOption, Index++);
}
InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd,
unsigned &MissingArgIndex,
unsigned &MissingArgCount) const {
InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
// FIXME: Handle '@' args (or at least error on them).
MissingArgIndex = MissingArgCount = 0;
unsigned Index = 0, End = ArgEnd - ArgBegin;
while (Index < End) {
// Ignore empty arguments (other things may still take them as arguments).
if (Args->getArgString(Index)[0] == '\0') {
++Index;
continue;
}
unsigned Prev = Index;
Arg *A = ParseOneArg(*Args, Index);
assert(Index > Prev && "Parser failed to consume argument.");
// Check for missing argument error.
if (!A) {
assert(Index >= End && "Unexpected parser error.");
assert(Index - Prev - 1 && "No missing arguments!");
MissingArgIndex = Prev;
MissingArgCount = Index - Prev - 1;
break;
}
Args->append(A);
}
return Args;
}