1 //===- MCLDInputTree.h ----------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef MCLD_INPUT_TREE_H
10 #define MCLD_INPUT_TREE_H
11 #ifdef ENABLE_UNITTEST
12 #include <gtest.h>
13 #endif
14
15 #include "mcld/ADT/BinTree.h"
16 #include "mcld/ADT/TypeTraits.h"
17 #include "mcld/MC/MCLDInput.h"
18 #include "mcld/MC/InputFactory.h"
19 #include "mcld/Support/FileSystem.h"
20
21 #include <string>
22
23
24 namespace mcld
25 {
26
27 /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
28 * \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
29 */
30 template<typename Traits, typename IteratorType>
31 class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType>
32 {
33 public:
34 typedef PolicyIterator<Input, Traits, IteratorType> Self;
35 typedef PolicyIteratorBase<Input, Traits, IteratorType> Base;
36 typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator;
37 typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType> const_iterator;
38
39 public:
PolicyIterator()40 PolicyIterator()
41 : Base() {}
42
PolicyIterator(const iterator & X)43 PolicyIterator(const iterator &X)
44 : Base(X.m_pNode) {}
45
PolicyIterator(NodeBase * X)46 explicit PolicyIterator(NodeBase* X)
47 : Base(X) {}
48
~PolicyIterator()49 virtual ~PolicyIterator() {}
50
isGroup()51 bool isGroup() const
52 { return !Base::hasData(); }
53
54 Self& operator++() {
55 IteratorType::advance();
56 if (isGroup())
57 IteratorType::advance();
58 return *this;
59 }
60
61 Self operator++(int) {
62 Self tmp(*this);
63 IteratorType::advance();
64 if (isGroup())
65 IteratorType::advance();
66 return tmp;
67 }
68 };
69
70 /** \class InputTree
71 * \brief InputTree is the input tree to contains all inputs from the
72 * command line.
73 *
74 * InputTree, of course, is uncopyable.
75 *
76 * @see Input
77 */
78 class InputTree : public BinaryTree<Input>
79 {
80 private:
81 typedef BinaryTree<Input> BinTreeTy;
82
83 public:
84 enum Direction {
85 Inclusive = TreeIteratorBase::Leftward,
86 Positional = TreeIteratorBase::Rightward
87 };
88
89 typedef BinaryTree<Input>::iterator iterator;
90 typedef BinaryTree<Input>::const_iterator const_iterator;
91
92 public:
93 struct Connector {
~ConnectorConnector94 virtual ~Connector() {}
95 virtual void connect(iterator& pFrom, const const_iterator& pTo) const = 0;
96 virtual void move(iterator& pNode) const = 0;
97 };
98
99 struct Succeeder : public Connector {
connectSucceeder100 virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
101 proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
102 }
103
moveSucceeder104 virtual void move(iterator& pNode) const {
105 pNode.move<Positional>();
106 }
107 };
108
109 struct Includer : public Connector {
connectIncluder110 virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
111 proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
112 }
113
moveIncluder114 virtual void move(iterator& pNode) const {
115 pNode.move<Inclusive>();
116 }
117 };
118
119 public:
120 static Succeeder Afterward;
121 static Includer Downward;
122
123 public:
124
125 using BinTreeTy::merge;
126
127 InputTree(InputFactory& pInputFactory);
128 ~InputTree();
129
130 // ----- modify ----- //
131 /// insert - create a leaf node and merge it in the tree.
132 // This version of join determines the direction at run time.
133 // @param position the parent node
134 // @param value the value being pushed.
135 // @param pConnector the direction of the connecting edge of the parent node.
136 template<size_t DIRECT>
137 InputTree& insert(iterator pPosition,
138 const std::string& pNamespec,
139 const sys::fs::Path& pPath,
140 unsigned int pType = Input::Unknown);
141
142 template<size_t DIRECT>
143 InputTree& enterGroup(iterator pPosition);
144
145 template<size_t DIRECT>
146 InputTree& insert(iterator pPosition,
147 const Input& pInput);
148
149 InputTree& merge(iterator pPosition,
150 const Connector& pConnector,
151 InputTree& pTree);
152
153 InputTree& insert(iterator pPosition,
154 const Connector& pConnector,
155 const std::string& pNamespec,
156 const sys::fs::Path& pPath,
157 unsigned int pType = Input::Unknown);
158
159 InputTree& insert(iterator pPosition,
160 const Connector& pConnector,
161 const Input& pInput);
162
163 InputTree& enterGroup(iterator pPosition,
164 const Connector& pConnector);
165
166 // ----- observers ----- //
numOfInputs()167 unsigned int numOfInputs() const
168 { return m_FileFactory.size(); }
169
hasInput()170 bool hasInput() const
171 { return !m_FileFactory.empty(); }
172
173 private:
174 InputFactory& m_FileFactory;
175
176 };
177
178 bool isGroup(const InputTree::iterator& pos);
179 bool isGroup(const InputTree::const_iterator& pos);
180 bool isGroup(const InputTree::dfs_iterator& pos);
181 bool isGroup(const InputTree::const_dfs_iterator& pos);
182 bool isGroup(const InputTree::bfs_iterator& pos);
183 bool isGroup(const InputTree::const_bfs_iterator& pos);
184
185 } // namespace of mcld
186
187 //===----------------------------------------------------------------------===//
188 // template member functions
189 template<size_t DIRECT>
190 mcld::InputTree&
insert(mcld::InputTree::iterator pPosition,const std::string & pNamespec,const mcld::sys::fs::Path & pPath,unsigned int pType)191 mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
192 const std::string& pNamespec,
193 const mcld::sys::fs::Path& pPath,
194 unsigned int pType)
195 {
196 BinTreeTy::node_type* node = createNode();
197 node->data = m_FileFactory.produce(pNamespec, pPath, pType);
198 if (pPosition.isRoot())
199 proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
200 const_cast<const node_type*>(node));
201 else
202 proxy::hook<DIRECT>(pPosition.m_pNode,
203 const_cast<const node_type*>(node));
204 return *this;
205 }
206
207 template<size_t DIRECT>
208 mcld::InputTree&
enterGroup(mcld::InputTree::iterator pPosition)209 mcld::InputTree::enterGroup(mcld::InputTree::iterator pPosition)
210 {
211 BinTreeTy::node_type* node = createNode();
212 if (pPosition.isRoot())
213 proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
214 const_cast<const node_type*>(node));
215 else
216 proxy::hook<DIRECT>(pPosition.m_pNode,
217 const_cast<const node_type*>(node));
218 return *this;
219 }
220
221 template<size_t DIRECT>
insert(mcld::InputTree::iterator pPosition,const mcld::Input & pInput)222 mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
223 const mcld::Input& pInput)
224 {
225 BinTreeTy::node_type* node = createNode();
226 node->data = const_cast<mcld::Input*>(&pInput);
227 if (pPosition.isRoot())
228 proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
229 const_cast<const node_type*>(node));
230 else
231 proxy::hook<DIRECT>(pPosition.m_pNode,
232 const_cast<const node_type*>(node));
233 return *this;
234 }
235
236 #endif
237
238