| //===--- Arg.cpp - Argument Implementations -----------------------------*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Driver/Arg.h" |
| #include "clang/Driver/ArgList.h" |
| #include "clang/Driver/Option.h" |
| #include "llvm/ADT/Twine.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace clang::driver; |
| |
| Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index, |
| const Arg *_BaseArg) |
| : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false) { |
| } |
| |
| Arg::~Arg() { } |
| |
| void Arg::dump() const { |
| llvm::errs() << "<"; |
| switch (Kind) { |
| default: |
| assert(0 && "Invalid kind"); |
| #define P(N) case N: llvm::errs() << #N; break |
| P(FlagClass); |
| P(PositionalClass); |
| P(JoinedClass); |
| P(SeparateClass); |
| P(CommaJoinedClass); |
| P(JoinedAndSeparateClass); |
| #undef P |
| } |
| |
| llvm::errs() << " Opt:"; |
| Opt->dump(); |
| |
| llvm::errs() << " Index:" << Index; |
| |
| if (isa<CommaJoinedArg>(this) || isa<SeparateArg>(this)) |
| llvm::errs() << " NumValues:" << getNumValues(); |
| |
| llvm::errs() << ">\n"; |
| } |
| |
| std::string Arg::getAsString(const ArgList &Args) const { |
| std::string Res; |
| llvm::raw_string_ostream OS(Res); |
| |
| ArgStringList ASL; |
| render(Args, ASL); |
| for (ArgStringList::iterator |
| it = ASL.begin(), ie = ASL.end(); it != ie; ++it) { |
| if (it != ASL.begin()) |
| OS << ' '; |
| OS << *it; |
| } |
| |
| return OS.str(); |
| } |
| |
| void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const { |
| if (!getOption().hasNoOptAsInput()) { |
| render(Args, Output); |
| return; |
| } |
| |
| for (unsigned i = 0, e = getNumValues(); i != e; ++i) |
| Output.push_back(getValue(Args, i)); |
| } |
| |
| FlagArg::FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg) |
| : Arg(FlagClass, Opt, Index, BaseArg) { |
| } |
| |
| void FlagArg::render(const ArgList &Args, ArgStringList &Output) const { |
| Output.push_back(Args.getArgString(getIndex())); |
| } |
| |
| const char *FlagArg::getValue(const ArgList &Args, unsigned N) const { |
| assert(0 && "Invalid index."); |
| return 0; |
| } |
| |
| PositionalArg::PositionalArg(const Option *Opt, unsigned Index, |
| const Arg *BaseArg) |
| : Arg(PositionalClass, Opt, Index, BaseArg) { |
| } |
| |
| void PositionalArg::render(const ArgList &Args, ArgStringList &Output) const { |
| Output.push_back(Args.getArgString(getIndex())); |
| } |
| |
| const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const { |
| assert(N < getNumValues() && "Invalid index."); |
| return Args.getArgString(getIndex()); |
| } |
| |
| JoinedArg::JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg) |
| : Arg(JoinedClass, Opt, Index, BaseArg) { |
| } |
| |
| void JoinedArg::render(const ArgList &Args, ArgStringList &Output) const { |
| if (getOption().hasForceSeparateRender()) { |
| Output.push_back(getOption().getName()); |
| Output.push_back(getValue(Args, 0)); |
| } else { |
| Output.push_back(Args.getArgString(getIndex())); |
| } |
| } |
| |
| const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const { |
| assert(N < getNumValues() && "Invalid index."); |
| // FIXME: Avoid strlen. |
| return Args.getArgString(getIndex()) + strlen(getOption().getName()); |
| } |
| |
| CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index, |
| const char *Str, const Arg *BaseArg) |
| : Arg(CommaJoinedClass, Opt, Index, BaseArg) { |
| const char *Prev = Str; |
| for (;; ++Str) { |
| char c = *Str; |
| |
| if (!c) { |
| if (Prev != Str) |
| Values.push_back(std::string(Prev, Str)); |
| break; |
| } else if (c == ',') { |
| if (Prev != Str) |
| Values.push_back(std::string(Prev, Str)); |
| Prev = Str + 1; |
| } |
| } |
| } |
| |
| void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const { |
| Output.push_back(Args.getArgString(getIndex())); |
| } |
| |
| const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const { |
| assert(N < getNumValues() && "Invalid index."); |
| return Values[N].c_str(); |
| } |
| |
| SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues, |
| const Arg *BaseArg) |
| : Arg(SeparateClass, Opt, Index, BaseArg), NumValues(_NumValues) { |
| } |
| |
| void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const { |
| if (getOption().hasForceJoinedRender()) { |
| assert(getNumValues() == 1 && "Cannot force joined render with > 1 args."); |
| Output.push_back(Args.MakeArgString(llvm::StringRef(getOption().getName()) + |
| getValue(Args, 0))); |
| } else { |
| Output.push_back(Args.getArgString(getIndex())); |
| for (unsigned i = 0; i < NumValues; ++i) |
| Output.push_back(getValue(Args, i)); |
| } |
| } |
| |
| const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const { |
| assert(N < getNumValues() && "Invalid index."); |
| return Args.getArgString(getIndex() + 1 + N); |
| } |
| |
| JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index, |
| const Arg *BaseArg) |
| : Arg(JoinedAndSeparateClass, Opt, Index, BaseArg) { |
| } |
| |
| void JoinedAndSeparateArg::render(const ArgList &Args, |
| ArgStringList &Output) const { |
| Output.push_back(Args.getArgString(getIndex())); |
| Output.push_back(Args.getArgString(getIndex() + 1)); |
| } |
| |
| const char *JoinedAndSeparateArg::getValue(const ArgList &Args, |
| unsigned N) const { |
| assert(N < getNumValues() && "Invalid index."); |
| if (N == 0) |
| return Args.getArgString(getIndex()) + strlen(getOption().getName()); |
| return Args.getArgString(getIndex() + 1); |
| } |