Linkloader improvement: mclinker.

Change-Id: I8805e39ccbc2ee204234fb3e71c70c906f3990bb
diff --git a/include/mcld/MC/MCLDInputTree.h b/include/mcld/MC/MCLDInputTree.h
new file mode 100644
index 0000000..7d8050c
--- /dev/null
+++ b/include/mcld/MC/MCLDInputTree.h
@@ -0,0 +1,237 @@
+//===- MCLDInputTree.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_INPUT_TREE_H
+#define MCLD_INPUT_TREE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include "mcld/ADT/BinTree.h"
+#include "mcld/ADT/TypeTraits.h"
+#include "mcld/MC/MCLDInput.h"
+#include "mcld/MC/InputFactory.h"
+#include "mcld/Support/FileSystem.h"
+
+#include <string>
+
+
+namespace mcld
+{
+
+/** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
+ *  \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
+ */
+template<typename Traits, typename IteratorType>
+class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType>
+{
+public:
+  typedef PolicyIterator<Input, Traits, IteratorType> Self;
+  typedef PolicyIteratorBase<Input, Traits, IteratorType> Base;
+  typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator;
+  typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType>    const_iterator;
+
+public:
+  PolicyIterator()
+    : Base() {}
+
+  PolicyIterator(const iterator &X)
+    : Base(X.m_pNode) {}
+
+  explicit PolicyIterator(NodeBase* X)
+    : Base(X) {}
+
+  virtual ~PolicyIterator() {}
+
+  bool isGroup() const
+  { return !Base::hasData(); }
+
+  Self& operator++() {
+    IteratorType::advance();
+    if (isGroup())
+      IteratorType::advance();
+    return *this;
+  }
+
+  Self operator++(int) {
+    Self tmp(*this);
+    IteratorType::advance();
+    if (isGroup())
+      IteratorType::advance();
+    return tmp;
+  }
+};
+
+/** \class InputTree
+ *  \brief InputTree is the input tree to contains all inputs from the
+ *  command line.
+ *
+ *  InputTree, of course, is uncopyable.
+ *
+ *  @see Input
+ */
+class InputTree : public BinaryTree<Input>
+{
+private:
+  typedef BinaryTree<Input> BinTreeTy;
+
+public:
+  enum Direction {
+    Inclusive  = TreeIteratorBase::Leftward,
+    Positional = TreeIteratorBase::Rightward
+  };
+
+  typedef BinaryTree<Input>::iterator       iterator;
+  typedef BinaryTree<Input>::const_iterator const_iterator;
+
+public:
+  struct Connector {
+    virtual ~Connector() {}
+    virtual void connect(iterator& pFrom, const const_iterator& pTo) const = 0;
+    virtual void move(iterator& pNode) const = 0;
+  };
+
+  struct Succeeder : public Connector {
+    virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
+      proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
+    }
+
+    virtual void move(iterator& pNode) const {
+      pNode.move<Positional>();
+    }
+  };
+
+  struct Includer : public Connector {
+    virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
+      proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
+    }
+
+    virtual void move(iterator& pNode) const {
+      pNode.move<Inclusive>();
+    }
+  };
+
+public:
+  static Succeeder Afterward;
+  static Includer  Downward;
+
+public:
+
+  using BinTreeTy::merge;
+
+  InputTree(InputFactory& pInputFactory);
+  ~InputTree();
+
+  // -----  modify  ----- //
+  /// insert - create a leaf node and merge it in the tree.
+  //  This version of join determines the direction at run time.
+  //  @param position the parent node
+  //  @param value the value being pushed.
+  //  @param pConnector the direction of the connecting edge of the parent node.
+  template<size_t DIRECT>
+  InputTree& insert(iterator pPosition,
+                    const std::string& pNamespec,
+                    const sys::fs::Path& pPath,
+                    unsigned int pType = Input::Unknown);
+
+  template<size_t DIRECT>
+  InputTree& enterGroup(iterator pPosition);
+
+  template<size_t DIRECT>
+  InputTree& insert(iterator pPosition,
+                    const Input& pInput);
+
+  InputTree& merge(iterator pPosition, 
+                   const Connector& pConnector,
+                   InputTree& pTree);
+
+  InputTree& insert(iterator pPosition,
+                    const Connector& pConnector,
+                    const std::string& pNamespec,
+                    const sys::fs::Path& pPath,
+                    unsigned int pType = Input::Unknown);
+
+  InputTree& insert(iterator pPosition,
+                    const Connector& pConnector,
+                    const Input& pInput);
+
+  InputTree& enterGroup(iterator pPosition,
+                        const Connector& pConnector);
+
+  // -----  observers  ----- //
+  unsigned int numOfInputs() const
+  { return m_FileFactory.size(); }
+
+  bool hasInput() const
+  { return !m_FileFactory.empty(); }
+
+private:
+  InputFactory& m_FileFactory;
+
+};
+
+bool isGroup(const InputTree::iterator& pos);
+bool isGroup(const InputTree::const_iterator& pos);
+bool isGroup(const InputTree::dfs_iterator& pos);
+bool isGroup(const InputTree::const_dfs_iterator& pos);
+bool isGroup(const InputTree::bfs_iterator& pos);
+bool isGroup(const InputTree::const_bfs_iterator& pos);
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// template member functions
+template<size_t DIRECT>
+mcld::InputTree&
+mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
+                        const std::string& pNamespec,
+                        const mcld::sys::fs::Path& pPath,
+                        unsigned int pType)
+{
+  BinTreeTy::node_type* node = createNode();
+  node->data = m_FileFactory.produce(pNamespec, pPath, pType); 
+  if (pPosition.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+        const_cast<const node_type*>(node));
+  else
+    proxy::hook<DIRECT>(pPosition.m_pNode,
+        const_cast<const node_type*>(node));
+  return *this;
+}
+
+template<size_t DIRECT>
+mcld::InputTree&
+mcld::InputTree::enterGroup(mcld::InputTree::iterator pPosition)
+{
+  BinTreeTy::node_type* node = createNode(); 
+  if (pPosition.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+        const_cast<const node_type*>(node));
+  else
+    proxy::hook<DIRECT>(pPosition.m_pNode,
+        const_cast<const node_type*>(node));
+  return *this;
+}
+
+template<size_t DIRECT>
+mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
+	                                 const mcld::Input& pInput)
+{
+  BinTreeTy::node_type* node = createNode();
+  node->data = const_cast<mcld::Input*>(&pInput);
+  if (pPosition.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+                                         const_cast<const node_type*>(node));
+  else
+    proxy::hook<DIRECT>(pPosition.m_pNode,
+                        const_cast<const node_type*>(node));
+  return *this;
+}
+
+#endif
+