blob: a09ba095f119d32ec0d4f969f272b4839d4a3b26 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//===--- Arg.cpp - Argument Implementations -----------------------------*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Driver/Arg.h"
11#include "clang/Driver/ArgList.h"
12#include "clang/Driver/Option.h"
13#include "llvm/Support/raw_ostream.h"
14
15using namespace clang::driver;
16
17Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index,
18 const Arg *_BaseArg)
19 : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false) {
20}
21
22Arg::~Arg() { }
23
24void Arg::dump() const {
25 llvm::errs() << "<";
26 switch (Kind) {
27 default:
28 assert(0 && "Invalid kind");
29#define P(N) case N: llvm::errs() << #N; break
30 P(FlagClass);
31 P(PositionalClass);
32 P(JoinedClass);
33 P(SeparateClass);
34 P(CommaJoinedClass);
35 P(JoinedAndSeparateClass);
36#undef P
37 }
38
39 llvm::errs() << " Opt:";
40 Opt->dump();
41
42 llvm::errs() << " Index:" << Index;
43
44 if (isa<CommaJoinedArg>(this) || isa<SeparateArg>(this))
45 llvm::errs() << " NumValues:" << getNumValues();
46
47 llvm::errs() << ">\n";
48}
49
50std::string Arg::getAsString(const ArgList &Args) const {
51 std::string Res;
52 llvm::raw_string_ostream OS(Res);
53
54 ArgStringList ASL;
55 render(Args, ASL);
56 for (ArgStringList::iterator
57 it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
58 if (it != ASL.begin())
59 OS << ' ';
60 OS << *it;
61 }
62
63 return OS.str();
64}
65
66void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
67 if (!getOption().hasNoOptAsInput()) {
68 render(Args, Output);
69 return;
70 }
71
72 for (unsigned i = 0, e = getNumValues(); i != e; ++i)
73 Output.push_back(getValue(Args, i));
74}
75
76FlagArg::FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
77 : Arg(FlagClass, Opt, Index, BaseArg) {
78}
79
80void FlagArg::render(const ArgList &Args, ArgStringList &Output) const {
81 Output.push_back(Args.getArgString(getIndex()));
82}
83
84const char *FlagArg::getValue(const ArgList &Args, unsigned N) const {
85 assert(0 && "Invalid index.");
86 return 0;
87}
88
89PositionalArg::PositionalArg(const Option *Opt, unsigned Index,
90 const Arg *BaseArg)
91 : Arg(PositionalClass, Opt, Index, BaseArg) {
92}
93
94void PositionalArg::render(const ArgList &Args, ArgStringList &Output) const {
95 Output.push_back(Args.getArgString(getIndex()));
96}
97
98const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const {
99 assert(N < getNumValues() && "Invalid index.");
100 return Args.getArgString(getIndex());
101}
102
103JoinedArg::JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
104 : Arg(JoinedClass, Opt, Index, BaseArg) {
105}
106
107void JoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
108 if (getOption().hasForceSeparateRender()) {
109 Output.push_back(getOption().getName());
110 Output.push_back(getValue(Args, 0));
111 } else {
112 Output.push_back(Args.getArgString(getIndex()));
113 }
114}
115
116const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const {
117 assert(N < getNumValues() && "Invalid index.");
118 // FIXME: Avoid strlen.
119 return Args.getArgString(getIndex()) + strlen(getOption().getName());
120}
121
122CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
123 const char *Str, const Arg *BaseArg)
124 : Arg(CommaJoinedClass, Opt, Index, BaseArg) {
125 const char *Prev = Str;
126 for (;; ++Str) {
127 char c = *Str;
128
129 if (!c) {
130 if (Prev != Str)
131 Values.push_back(std::string(Prev, Str));
132 break;
133 } else if (c == ',') {
134 if (Prev != Str)
135 Values.push_back(std::string(Prev, Str));
136 Prev = Str + 1;
137 }
138 }
139}
140
141void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
142 Output.push_back(Args.getArgString(getIndex()));
143}
144
145const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const {
146 assert(N < getNumValues() && "Invalid index.");
147 return Values[N].c_str();
148}
149
150SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues,
151 const Arg *BaseArg)
152 : Arg(SeparateClass, Opt, Index, BaseArg), NumValues(_NumValues) {
153}
154
155void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const {
156 if (getOption().hasForceJoinedRender()) {
157 assert(getNumValues() == 1 && "Cannot force joined render with > 1 args.");
158 // FIXME: Avoid std::string.
159 std::string Joined(getOption().getName());
160 Joined += Args.getArgString(getIndex());
161 Output.push_back(Args.MakeArgString(Joined.c_str()));
162 } else {
163 Output.push_back(Args.getArgString(getIndex()));
164 for (unsigned i = 0; i < NumValues; ++i)
165 Output.push_back(Args.getArgString(getIndex() + 1 + i));
166 }
167}
168
169const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
170 assert(N < getNumValues() && "Invalid index.");
171 return Args.getArgString(getIndex() + 1 + N);
172}
173
174JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index,
175 const Arg *BaseArg)
176 : Arg(JoinedAndSeparateClass, Opt, Index, BaseArg) {
177}
178
179void JoinedAndSeparateArg::render(const ArgList &Args,
180 ArgStringList &Output) const {
181 Output.push_back(Args.getArgString(getIndex()));
182 Output.push_back(Args.getArgString(getIndex() + 1));
183}
184
185const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
186 unsigned N) const {
187 assert(N < getNumValues() && "Invalid index.");
188 if (N == 0)
189 return Args.getArgString(getIndex()) + strlen(getOption().getName());
190 return Args.getArgString(getIndex() + 1);
191}