//===--- 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/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(this) || isa(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."); // FIXME: Avoid std::string. std::string Joined(getOption().getName()); Joined += Args.getArgString(getIndex()); Output.push_back(Args.MakeArgString(Joined.c_str())); } else { Output.push_back(Args.getArgString(getIndex())); for (unsigned i = 0; i < NumValues; ++i) Output.push_back(Args.getArgString(getIndex() + 1 + 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); }