From 5640c382da13e671be5a6b208b37ba9c19795785 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Sun, 29 Dec 2019 01:12:20 +0800
Subject: [PATCH] >  Manual commit:  adjust build scripts, add rlib:header-only
 as dependency U201614531 recolic Linux RECOLICPC 5.4.6-arch3-1 #1 SMP PREEMPT
 Tue, 24 Dec 2019 04:36:53 +0000 x86_64 GNU/Linux  01:12:20 up  6:46,  1 user,
  load average: 0.78, 0.96, 0.84 f75a49b365c304508914ace65c3ec1846b875c2

---
 .gitlab-ci.yml                               |  12 +
 nemu/Makefile                                |  18 +-
 nemu/include/rlib/.gitignore                 |  34 +
 nemu/include/rlib/3rdparty/prettyprint.hpp   | 461 +++++++++++++
 nemu/include/rlib/3rdparty/prettyprint98.hpp | 410 ++++++++++++
 nemu/include/rlib/3rdparty/test.cc           |   9 +
 nemu/include/rlib/LICENSE                    |  21 +
 nemu/include/rlib/Makefile                   |  33 +
 nemu/include/rlib/README.md                  |  20 +
 nemu/include/rlib/buildspec.yaml             |  17 +
 nemu/include/rlib/c-with-class.h             |  27 +
 nemu/include/rlib/class_decorator.hpp        |  47 ++
 nemu/include/rlib/cmake/CMakeLists.txt       |  18 +
 nemu/include/rlib/cmake/cmake.include        |  15 +
 nemu/include/rlib/cmake/rlib-config.cmake    |  17 +
 nemu/include/rlib/functional.hpp             | 125 ++++
 nemu/include/rlib/impl/traceable_list.hpp    | 225 +++++++
 nemu/include/rlib/log.hpp                    | 188 ++++++
 nemu/include/rlib/macro.hpp                  |  34 +
 nemu/include/rlib/meta.hpp                   |  59 ++
 nemu/include/rlib/opt.hpp                    | 126 ++++
 nemu/include/rlib/pool.hpp                   | 129 ++++
 nemu/include/rlib/require/cxx11              |  12 +
 nemu/include/rlib/require/cxx14              |  12 +
 nemu/include/rlib/require/cxx17              |  13 +
 nemu/include/rlib/scope_guard.hpp            | 100 +++
 nemu/include/rlib/stdio.hpp                  | 243 +++++++
 nemu/include/rlib/stream.hpp                 |  24 +
 nemu/include/rlib/string.hpp                 | 410 ++++++++++++
 nemu/include/rlib/sys/cc_codegen.py          |  43 ++
 nemu/include/rlib/sys/cc_list                |  71 ++
 nemu/include/rlib/sys/compiler_detector      | 495 ++++++++++++++
 nemu/include/rlib/sys/fd.hpp                 |  14 +
 nemu/include/rlib/sys/os.hpp                 |  98 +++
 nemu/include/rlib/sys/rwlock.hpp             |  22 +
 nemu/include/rlib/sys/sio.hpp                | 664 +++++++++++++++++++
 nemu/include/rlib/sys/time.hpp               |  18 +
 nemu/include/rlib/sys/unix_handy.hpp         | 170 +++++
 nemu/include/rlib/terminal.hpp               | 100 +++
 nemu/include/rlib/traits.hpp                 |  38 ++
 nemu/runall.sh                               |  24 +-
 41 files changed, 4601 insertions(+), 15 deletions(-)
 create mode 100644 .gitlab-ci.yml
 create mode 100644 nemu/include/rlib/.gitignore
 create mode 100644 nemu/include/rlib/3rdparty/prettyprint.hpp
 create mode 100644 nemu/include/rlib/3rdparty/prettyprint98.hpp
 create mode 100644 nemu/include/rlib/3rdparty/test.cc
 create mode 100644 nemu/include/rlib/LICENSE
 create mode 100644 nemu/include/rlib/Makefile
 create mode 100644 nemu/include/rlib/README.md
 create mode 100644 nemu/include/rlib/buildspec.yaml
 create mode 100644 nemu/include/rlib/c-with-class.h
 create mode 100644 nemu/include/rlib/class_decorator.hpp
 create mode 100644 nemu/include/rlib/cmake/CMakeLists.txt
 create mode 100644 nemu/include/rlib/cmake/cmake.include
 create mode 100644 nemu/include/rlib/cmake/rlib-config.cmake
 create mode 100644 nemu/include/rlib/functional.hpp
 create mode 100644 nemu/include/rlib/impl/traceable_list.hpp
 create mode 100644 nemu/include/rlib/log.hpp
 create mode 100644 nemu/include/rlib/macro.hpp
 create mode 100644 nemu/include/rlib/meta.hpp
 create mode 100644 nemu/include/rlib/opt.hpp
 create mode 100644 nemu/include/rlib/pool.hpp
 create mode 100644 nemu/include/rlib/require/cxx11
 create mode 100644 nemu/include/rlib/require/cxx14
 create mode 100644 nemu/include/rlib/require/cxx17
 create mode 100644 nemu/include/rlib/scope_guard.hpp
 create mode 100644 nemu/include/rlib/stdio.hpp
 create mode 100644 nemu/include/rlib/stream.hpp
 create mode 100644 nemu/include/rlib/string.hpp
 create mode 100755 nemu/include/rlib/sys/cc_codegen.py
 create mode 100644 nemu/include/rlib/sys/cc_list
 create mode 100644 nemu/include/rlib/sys/compiler_detector
 create mode 100644 nemu/include/rlib/sys/fd.hpp
 create mode 100644 nemu/include/rlib/sys/os.hpp
 create mode 100644 nemu/include/rlib/sys/rwlock.hpp
 create mode 100644 nemu/include/rlib/sys/sio.hpp
 create mode 100644 nemu/include/rlib/sys/time.hpp
 create mode 100644 nemu/include/rlib/sys/unix_handy.hpp
 create mode 100644 nemu/include/rlib/terminal.hpp
 create mode 100644 nemu/include/rlib/traits.hpp
 mode change 100644 => 100755 nemu/runall.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..3ba3997
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,12 @@
+image: archlinux/base
+
+stages:
+    - build
+
+build:
+    stage: build
+    script: 
+        - pacman -Sy && pacman -S --noconfirm bison flex gcc make gettext sdl2 lib32-glibc
+        - export AM_HOME=$(pwd)/nexus-am/
+        - cd nemu && make && show_log=1 ./runall.sh
+
diff --git a/nemu/Makefile b/nemu/Makefile
index 2a7eb67..e058045 100644
--- a/nemu/Makefile
+++ b/nemu/Makefile
@@ -22,8 +22,13 @@ INCLUDES  = $(addprefix -I, $(INC_DIR))
 CFLAGS   += -O2 -MMD -Wall -ggdb3 $(INCLUDES) -fomit-frame-pointer -std=c++17
 CFLAGS   += -DDIFF_TEST_QEMU
 
+# Source code generation before any targets.
+SUBDIRS = src/monitor/debug/expr_impl
+$(SUBDIRS):
+	$(MAKE) -C $@
+
 # Files to be compiled
-SRCS = $(shell find src/ -name "*.cc")
+SRCS = $(shell make -C $(SUBDIRS) generate 1>&2 && find src/ -name "*.cc")
 OBJS = $(SRCS:src/%.cc=$(OBJ_DIR)/%.o)
 
 # Compilation patterns
@@ -32,18 +37,12 @@ $(OBJ_DIR)/%.o: src/%.cc
 	@mkdir -p $(dir $@)
 	$(CXX) $(CFLAGS) $(SO_CFLAGS) -c -o $@ $<
 
-
 # Depencies
 -include $(OBJS:.o=.d)
 
-# Source code generation before any targets.
-SUBDIRS = src/monitor/debug/expr_impl
-$(SUBDIRS):
-	$(MAKE) -C $@
-
 # Some convinient rules
 .PHONY: app run clean $(SUBDIRS)
-app: $(SUBDIRS) $(BINARY)
+app: $(BINARY)
 
 override ARGS ?= -l $(BUILD_DIR)/nemu-log.txt
 override ARGS += -d $(NEMU_HOME)/tools/qemu-diff/build/qemu-so
@@ -54,7 +53,7 @@ NEMU_EXEC := $(BINARY) $(ARGS)
 $(BINARY): $(OBJS)
 	$(call git_commit, "compile")
 	@echo + LD $@
-	@$(LD) -O2 -rdynamic $(SO_LDLAGS) -o $@ $^ -lSDL2 -lreadline -ldl -lr
+	@$(LD) -O2 -rdynamic $(SO_LDLAGS) -o $@ $^ -lSDL2 -lreadline -ldl
 
 run: $(BINARY)
 	$(call git_commit, "run")
@@ -68,3 +67,4 @@ clean:
 	-rm -rf $(BUILD_DIR)
 	$(MAKE) -C tools/gen-expr clean
 	$(MAKE) -C tools/qemu-diff clean
+	$(MAKE) -C $(SUBDIRS) clean
diff --git a/nemu/include/rlib/.gitignore b/nemu/include/rlib/.gitignore
new file mode 100644
index 0000000..4f2c09b
--- /dev/null
+++ b/nemu/include/rlib/.gitignore
@@ -0,0 +1,34 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+.vscode/
+.idea/
+*.gi
+tmp/
diff --git a/nemu/include/rlib/3rdparty/prettyprint.hpp b/nemu/include/rlib/3rdparty/prettyprint.hpp
new file mode 100644
index 0000000..ce2226a
--- /dev/null
+++ b/nemu/include/rlib/3rdparty/prettyprint.hpp
@@ -0,0 +1,461 @@
+//          Copyright Louis Delacroix 2010 - 2014.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+//
+// A pretty printing library for C++
+//
+// Usage:
+// Include this header, and operator<< will "just work".
+
+#ifndef H_PRETTY_PRINT
+#define H_PRETTY_PRINT
+
+// Recolic add
+#if _GLIBCXX_OSTREAM
+#include <rlib/sys/os.hpp>
+#if RLIB_COMPILER_ID == CC_CLANG
+#error In clang, you must include prettyprint.hpp before STD ostream or rlib/stdio.hpp.
+#endif
+#endif
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <tuple>
+#include <type_traits>
+#include <unordered_set>
+#include <utility>
+#include <valarray>
+
+#ifndef RLIB_3RD_ENABLE_PRETTYPRINT
+namespace rlib {
+    namespace _3rdparty {
+#endif
+namespace pretty_print
+{
+    namespace detail
+    {
+        // SFINAE type trait to detect whether T::const_iterator exists.
+
+        struct sfinae_base
+        {
+            using yes = char;
+            using no  = yes[2];
+        };
+
+        template <typename T>
+        struct has_const_iterator : private sfinae_base
+        {
+        private:
+            template <typename C> static yes & test(typename C::const_iterator*);
+            template <typename C> static no  & test(...);
+        public:
+            static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
+            using type =  T;
+        };
+
+        template <typename T>
+        struct has_begin_end : private sfinae_base
+        {
+        private:
+            template <typename C>
+            static yes & f(typename std::enable_if<
+                std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
+                             typename C::const_iterator(C::*)() const>::value>::type *);
+
+            template <typename C> static no & f(...);
+
+            template <typename C>
+            static yes & g(typename std::enable_if<
+                std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
+                             typename C::const_iterator(C::*)() const>::value, void>::type*);
+
+            template <typename C> static no & g(...);
+
+        public:
+            static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
+            static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
+        };
+
+    }  // namespace detail
+
+
+    // Holds the delimiter values for a specific character type
+
+    template <typename TChar>
+    struct delimiters_values
+    {
+        using char_type = TChar;
+        const char_type * prefix;
+        const char_type * delimiter;
+        const char_type * postfix;
+    };
+
+
+    // Defines the delimiter values for a specific container and character type
+
+    template <typename T, typename TChar>
+    struct delimiters
+    {
+        using type = delimiters_values<TChar>;
+        static const type values; 
+    };
+
+
+    // Functor to print containers. You can use this directly if you want
+    // to specificy a non-default delimiters type. The printing logic can
+    // be customized by specializing the nested template.
+
+    template <typename T,
+              typename TChar = char,
+              typename TCharTraits = ::std::char_traits<TChar>,
+              typename TDelimiters = delimiters<T, TChar>>
+    struct print_container_helper
+    {
+        using delimiters_type = TDelimiters;
+        using ostream_type = std::basic_ostream<TChar, TCharTraits>;
+
+        template <typename U>
+        struct printer
+        {
+            static void print_body(const U & c, ostream_type & stream)
+            {
+                using std::begin;
+                using std::end;
+
+                auto it = begin(c);
+                const auto the_end = end(c);
+
+                if (it != the_end)
+                {
+                    for ( ; ; )
+                    {
+                        stream << *it;
+
+                    if (++it == the_end) break;
+
+                    if (delimiters_type::values.delimiter != NULL)
+                        stream << delimiters_type::values.delimiter;
+                    }
+                }
+            }
+        };
+
+        print_container_helper(const T & container)
+        : container_(container)
+        { }
+
+        inline void operator()(ostream_type & stream) const
+        {
+            if (delimiters_type::values.prefix != NULL)
+                stream << delimiters_type::values.prefix;
+
+            printer<T>::print_body(container_, stream);
+
+            if (delimiters_type::values.postfix != NULL)
+                stream << delimiters_type::values.postfix;
+        }
+
+    private:
+        const T & container_;
+    };
+
+    // Specialization for pairs
+
+    template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
+    template <typename T1, typename T2>
+    struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>>
+    {
+        using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
+
+        static void print_body(const std::pair<T1, T2> & c, ostream_type & stream)
+        {
+            stream << c.first;
+            if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
+                stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
+            stream << c.second;
+        }
+    };
+
+    // Specialization for tuples
+
+    template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
+    template <typename ...Args>
+    struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>>
+    {
+        using ostream_type = typename print_container_helper<T, TChar, TCharTraits, TDelimiters>::ostream_type;
+        using element_type = std::tuple<Args...>;
+
+        template <std::size_t I> struct Int { };
+
+        static void print_body(const element_type & c, ostream_type & stream)
+        {
+            tuple_print(c, stream, Int<0>());
+        }
+
+        static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>)
+        {
+        }
+
+        static void tuple_print(const element_type & c, ostream_type & stream,
+                                typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type)
+        {
+            stream << std::get<0>(c);
+            tuple_print(c, stream, Int<1>());
+        }
+
+        template <std::size_t N>
+        static void tuple_print(const element_type & c, ostream_type & stream, Int<N>)
+        {
+            if (print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter != NULL)
+                stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
+
+            stream << std::get<N>(c);
+
+            tuple_print(c, stream, Int<N + 1>());
+        }
+    };
+
+    // Prints a print_container_helper to the specified stream.
+
+    template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
+    inline std::basic_ostream<TChar, TCharTraits> & operator<<(
+        std::basic_ostream<TChar, TCharTraits> & stream,
+        const print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
+    {
+        helper(stream);
+        return stream;
+    }
+
+
+    // Basic is_container template; specialize to derive from std::true_type for all desired container types
+
+    template <typename T>
+    struct is_container : public std::integral_constant<bool,
+                                                        detail::has_const_iterator<T>::value &&
+                                                        detail::has_begin_end<T>::beg_value  &&
+                                                        detail::has_begin_end<T>::end_value> { };
+
+    template <typename T, std::size_t N>
+    struct is_container<T[N]> : std::true_type { };
+
+    template <std::size_t N>
+    struct is_container<char[N]> : std::false_type { };
+
+    template <typename T>
+    struct is_container<std::valarray<T>> : std::true_type { };
+
+    template <typename T1, typename T2>
+    struct is_container<std::pair<T1, T2>> : std::true_type { };
+
+    template <typename ...Args>
+    struct is_container<std::tuple<Args...>> : std::true_type { };
+
+
+    // Default delimiters
+
+    template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
+    template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
+    template <typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
+    template <typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
+
+
+    // Delimiters for (multi)set and unordered_(multi)set
+
+    template <typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template <typename T, typename TComp, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template <typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template <typename T, typename TComp, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+    template <typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template <typename T, typename TComp, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template <typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template <typename T, typename TComp, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template <typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+
+    // Delimiters for pair and tuple
+
+    template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
+    template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
+    template <typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
+    template <typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
+
+    template <typename ...Args> struct delimiters<std::tuple<Args...>, char> { static const delimiters_values<char> values; };
+    template <typename ...Args> const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = { "(", ", ", ")" };
+    template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; };
+    template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" };
+
+
+    // Type-erasing helper class for easy use of custom delimiters.
+    // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
+    // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
+
+    struct custom_delims_base
+    {
+        virtual ~custom_delims_base() { }
+        virtual std::ostream & stream(::std::ostream &) = 0;
+        virtual std::wostream & stream(::std::wostream &) = 0;
+    };
+
+    template <typename T, typename Delims>
+    struct custom_delims_wrapper : custom_delims_base
+    {
+        custom_delims_wrapper(const T & t_) : t(t_) { }
+
+        std::ostream & stream(std::ostream & s)
+        {
+            return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
+        }
+
+        std::wostream & stream(std::wostream & s)
+        {
+            return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
+        }
+
+    private:
+        const T & t;
+    };
+
+    template <typename Delims>
+    struct custom_delims
+    {
+        template <typename Container>
+        custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
+
+        std::unique_ptr<custom_delims_base> base;
+    };
+
+    template <typename TChar, typename TCharTraits, typename Delims>
+    inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p)
+    {
+        return p.base->stream(s);
+    }
+
+
+    // A wrapper for a C-style array given as pointer-plus-size.
+    // Usage: std::cout << pretty_print_array(arr, n) << std::endl;
+
+    template<typename T>
+    struct array_wrapper_n
+    {
+        typedef const T * const_iterator;
+        typedef T value_type;
+
+        array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
+        inline const_iterator begin() const { return _array; }
+        inline const_iterator end() const { return _array + _n; }
+
+    private:
+        const T * const _array;
+        size_t _n;
+    };
+
+
+    // A wrapper for hash-table based containers that offer local iterators to each bucket.
+    // Usage: std::cout << bucket_print(m, 4) << std::endl;  (Prints bucket 5 of container m.)
+
+    template <typename T>
+    struct bucket_print_wrapper
+    {
+        typedef typename T::const_local_iterator const_iterator;
+        typedef typename T::size_type size_type;
+
+        const_iterator begin() const
+        {
+            return m_map.cbegin(n);
+        }
+
+        const_iterator end() const
+        {
+            return m_map.cend(n);
+        }
+
+        bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
+
+    private:
+        const T & m_map;
+        const size_type n;
+    };
+
+}   // namespace pretty_print
+
+
+// Global accessor functions for the convenience wrappers
+
+template<typename T>
+inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
+{
+    return pretty_print::array_wrapper_n<T>(a, n);
+}
+
+template <typename T> pretty_print::bucket_print_wrapper<T>
+bucket_print(const T & m, typename T::size_type n)
+{
+    return pretty_print::bucket_print_wrapper<T>(m, n);
+}
+
+
+// Main magic entry point: An overload snuck into namespace std.
+// Can we do better?
+
+namespace std
+{
+    // Prints a container to the stream using default delimiters
+
+    template<typename T, typename TChar, typename TCharTraits>
+    inline typename ::std::enable_if< pretty_print::is_container<T>::value,
+                              ::std::basic_ostream<TChar, TCharTraits> &>::type
+    operator<<(::std::basic_ostream<TChar, TCharTraits> & stream, const T & container)
+    {
+        return stream << pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
+    }
+}
+#ifndef RLIB_3RD_ENABLE_PRETTYPRINT
+    }
+} // end namespace rlib::3rdparty
+#endif // RLIB_3RD_ENABLE_PRETTYPRINT 
+
+
+
+#endif  // H_PRETTY_PRINT
diff --git a/nemu/include/rlib/3rdparty/prettyprint98.hpp b/nemu/include/rlib/3rdparty/prettyprint98.hpp
new file mode 100644
index 0000000..112600b
--- /dev/null
+++ b/nemu/include/rlib/3rdparty/prettyprint98.hpp
@@ -0,0 +1,410 @@
+//          Copyright Louis Delacroix 2010 - 2014.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef H_PRETTY_PRINT
+#define H_PRETTY_PRINT
+
+
+#include <ostream>
+#include <utility>
+#include <iterator>
+#include <set>
+
+#ifndef NO_TR1
+#  include <tr1/tuple>
+#  include <tr1/unordered_set>
+#endif
+
+namespace pretty_print
+{
+
+    template <bool, typename S, typename T> struct conditional { };
+    template <typename S, typename T> struct conditional<true,  S, T> { typedef S type; };
+    template <typename S, typename T> struct conditional<false, S, T> { typedef T type; };
+
+    template <bool, typename T> struct enable_if { };
+    template <typename T> struct enable_if<true, T> { typedef T type; };
+
+    // SFINAE type trait to detect whether T::const_iterator exists.
+
+    template<typename T>
+    struct has_const_iterator
+    {
+    private:
+        typedef char                      yes;
+        typedef struct { char array[2]; } no;
+
+        template<typename C> static yes test(typename C::const_iterator*);
+        template<typename C> static no  test(...);
+    public:
+        static const bool value = sizeof(test<T>(0)) == sizeof(yes);
+        typedef T type;
+    };
+
+    // SFINAE type trait to detect whether "T::const_iterator T::begin/end() const" exist.
+
+    template <typename T>
+    struct has_begin_end
+    {
+        struct Dummy { typedef void const_iterator; };
+        typedef typename conditional<has_const_iterator<T>::value, T, Dummy>::type TType;
+        typedef typename TType::const_iterator iter;
+
+        struct Fallback { iter begin() const; iter end() const; };
+        struct Derived : TType, Fallback { };
+
+        template<typename C, C> struct ChT;
+
+        template<typename C> static char (&f(ChT<iter (Fallback::*)() const, &C::begin>*))[1];
+        template<typename C> static char (&f(...))[2];
+        template<typename C> static char (&g(ChT<iter (Fallback::*)() const, &C::end>*))[1];
+        template<typename C> static char (&g(...))[2];
+
+        static bool const beg_value = sizeof(f<Derived>(0)) == 2;
+        static bool const end_value = sizeof(g<Derived>(0)) == 2;
+    };
+
+    // Basic is_container template; specialize to have value "true" for all desired container types
+
+    template<typename T> struct is_container { static const bool value = has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value; };
+
+    template<typename T, std::size_t N> struct is_container<T[N]> { static const bool value = true; };
+
+    template<std::size_t N> struct is_container<char[N]> { static const bool value = false; };
+
+
+    // Holds the delimiter values for a specific character type
+
+    template<typename TChar>
+    struct delimiters_values
+    {
+        typedef TChar char_type;
+        const TChar * prefix;
+        const TChar * delimiter;
+        const TChar * postfix;
+    };
+
+
+    // Defines the delimiter values for a specific container and character type
+
+    template<typename T, typename TChar>
+    struct delimiters
+    {
+        typedef delimiters_values<TChar> type;
+        static const type values; 
+    };
+
+
+    // Default delimiters
+
+    template<typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
+    template<typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
+    template<typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
+    template<typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
+
+
+    // Delimiters for (multi)set and unordered_(multi)set
+
+    template<typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template<typename T, typename TComp, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template<typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template<typename T, typename TComp, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+    template<typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template<typename T, typename TComp, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template<typename T, typename TComp, typename TAllocator>
+    struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template<typename T, typename TComp, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+#ifndef NO_TR1
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<char> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
+
+    template<typename T, typename THash, typename TEqual, typename TAllocator>
+    const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
+#endif
+
+
+    // Delimiters for pair (reused for tuple, see below)
+
+    template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
+    template<typename T1, typename T2> const delimiters_values<char> delimiters< ::std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
+    template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
+    template<typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
+
+
+    // Iterator microtrait class to handle C arrays uniformly
+
+    template <typename T> struct get_iterator { typedef typename T::const_iterator iter; };
+    template <typename T, std::size_t N> struct get_iterator<T[N]> { typedef const T * iter; };
+
+    template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type begin(const T & c) { return c.begin(); }
+    template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type end(const T & c) { return c.end(); }
+    template <typename T, size_t N> const T * begin(const T(&x)[N]) { return &x[0];     }
+    template <typename T, size_t N> const T * end  (const T(&x)[N]) { return &x[0] + N; }
+
+    // Functor to print containers. You can use this directly if you want to specificy a non-default delimiters type.
+
+    template<typename T, typename TChar = char, typename TCharTraits = ::std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar> >
+    struct print_container_helper
+    {
+        typedef TChar char_type;
+        typedef TDelimiters delimiters_type;
+        typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
+        typedef typename get_iterator<T>::iter TIter;
+
+        print_container_helper(const T & container)
+        : _container(container)
+        {
+        }
+
+        inline void operator()(ostream_type & stream) const
+        {
+            if (delimiters_type::values.prefix != NULL)
+                stream << delimiters_type::values.prefix;
+
+            if (begin(_container) != end(_container))
+            for (TIter it = begin(_container), it_end = end(_container); ; )
+            {
+                stream << *it;
+
+                if (++it == it_end) break;
+
+                if (delimiters_type::values.delimiter != NULL)
+                    stream << delimiters_type::values.delimiter;
+            }
+
+            if (delimiters_type::values.postfix != NULL)
+                stream << delimiters_type::values.postfix;
+        }
+
+    private:
+        const T & _container;
+    };
+
+
+    // Type-erasing helper class for easy use of custom delimiters.
+    // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
+    // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
+
+    struct custom_delims_base
+    {
+        virtual ~custom_delims_base() { }
+        virtual ::std::ostream & stream(::std::ostream &) = 0;
+        virtual ::std::wostream & stream(::std::wostream &) = 0;
+    };
+
+    template<typename T, typename Delims>
+    struct custom_delims_wrapper : public custom_delims_base
+    {
+        custom_delims_wrapper(const T & t_) : t(t_) { }
+
+        ::std::ostream & stream(::std::ostream & s)
+        {
+          return s << ::pretty_print::print_container_helper<T, char, ::std::char_traits<char>, Delims>(t);
+        }
+        ::std::wostream & stream(::std::wostream & s)
+        {
+          return s << ::pretty_print::print_container_helper<T, wchar_t, ::std::char_traits<wchar_t>, Delims>(t);
+        }
+
+    private:
+        const T & t;
+    };
+
+    template<typename Delims>
+    struct custom_delims
+    {
+        template<typename Container> custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
+        ~custom_delims() { delete base; }
+        custom_delims_base * base;
+    };
+
+} // namespace pretty_print
+
+template<typename TChar, typename TCharTraits, typename Delims>
+inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const pretty_print::custom_delims<Delims> & p)
+{
+    return p.base->stream(s);
+}
+
+// Template aliases for char and wchar_t delimiters
+// Enable these if you have compiler support
+//
+// Implement as "template<T, C, A> const sdelims::type sdelims<std::set<T,C,A>>::values = { ... }."
+
+//template<typename T> using pp_sdelims = pretty_print::delimiters<T, char>;
+//template<typename T> using pp_wsdelims = pretty_print::delimiters<T, wchar_t>;
+
+
+namespace std
+{
+    // Prints a print_container_helper to the specified stream.
+
+    template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
+    inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream,
+                                                          const ::pretty_print::print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
+    {
+        helper(stream);
+        return stream;
+    }
+
+    // Prints a container to the stream using default delimiters
+
+    template<typename T, typename TChar, typename TCharTraits>
+    inline typename ::pretty_print::enable_if< ::pretty_print::is_container<T>::value, basic_ostream<TChar, TCharTraits>&>::type
+    operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
+    {
+        return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
+    }
+
+    // Prints a pair to the stream using delimiters from delimiters<std::pair<T1, T2>>.
+    template<typename T1, typename T2, typename TChar, typename TCharTraits>
+    inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const pair<T1, T2> & value)
+    {
+        if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix != NULL)
+            stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix;
+
+        stream << value.first;
+
+        if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter != NULL)
+            stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter;
+
+        stream << value.second;
+
+        if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix != NULL)
+            stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix;
+
+        return stream;
+    }
+} // namespace std
+
+
+#ifndef NO_TR1
+
+// Prints a tuple to the stream using delimiters from delimiters<std::pair<tuple_dummy_t, tuple_dummy_t>>.
+
+namespace pretty_print
+{
+    struct tuple_dummy_t { }; // Just if you want special delimiters for tuples.
+
+    typedef std::pair<tuple_dummy_t, tuple_dummy_t> tuple_dummy_pair;
+
+    template<typename Tuple, size_t N, typename TChar, typename TCharTraits>
+    struct pretty_tuple_helper
+    {
+        static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
+        {
+            pretty_tuple_helper<Tuple, N - 1, TChar, TCharTraits>::print(stream, value);
+
+            if (delimiters<tuple_dummy_pair, TChar>::values.delimiter != NULL)
+                stream << delimiters<tuple_dummy_pair, TChar>::values.delimiter;
+
+            stream << std::tr1::get<N - 1>(value);
+        }
+    };
+
+    template<typename Tuple, typename TChar, typename TCharTraits>
+    struct pretty_tuple_helper<Tuple, 1, TChar, TCharTraits>
+    {
+        static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
+        {
+            stream << ::std::tr1::get<0>(value);
+        }
+    };
+} // namespace pretty_print
+
+
+/* The following macros allow us to write "template <TUPLE_PARAMAS> std::tuple<TUPLE_ARGS>"
+ * uniformly in C++0x compilers and in MS Visual Studio 2010.
+ * Credits to STL: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-6-of-n
+ */
+
+#define TUPLE_PARAMS \
+    typename T0, typename T1, typename T2, typename T3, typename T4,      \
+    typename T5, typename T6, typename T7, typename T8, typename T9
+#define TUPLE_ARGS T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
+
+
+namespace std
+{
+    template<typename TChar, typename TCharTraits, TUPLE_PARAMS>
+    inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const tr1::tuple<TUPLE_ARGS> & value)
+    {
+        if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix != NULL)
+            stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix;
+
+        ::pretty_print::pretty_tuple_helper<const tr1::tuple<TUPLE_ARGS> &, tr1::tuple_size<tr1::tuple<TUPLE_ARGS> >::value, TChar, TCharTraits>::print(stream, value);
+
+        if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix != NULL)
+            stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix;
+
+        return stream;
+    }
+} // namespace std
+
+#endif // NO_TR1
+
+
+// A wrapper for raw C-style arrays. Usage: int arr[] = { 1, 2, 4, 8, 16 };  std::cout << wrap_array(arr) << ...
+
+namespace pretty_print
+{
+    template<typename T>
+    struct array_wrapper_n
+    {
+        typedef const T * const_iterator;
+        typedef T value_type;
+
+        array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
+        inline const_iterator begin() const { return _array; }
+        inline const_iterator end() const { return _array + _n; }
+
+    private:
+        const T * const _array;
+        size_t _n;
+    };
+} // namespace pretty_print
+
+template<typename T>
+inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
+{
+  return pretty_print::array_wrapper_n<T>(a, n);
+}
+
+
+#endif
diff --git a/nemu/include/rlib/3rdparty/test.cc b/nemu/include/rlib/3rdparty/test.cc
new file mode 100644
index 0000000..89a3519
--- /dev/null
+++ b/nemu/include/rlib/3rdparty/test.cc
@@ -0,0 +1,9 @@
+#include "prettyprint.hpp"
+#include <rlib/stdio.hpp>
+#include <list>
+using namespace rlib;
+
+int main() {
+    std::list ls {1,3,2};
+    _3rdparty::std::operator<<(std::cout, ls);
+}
diff --git a/nemu/include/rlib/LICENSE b/nemu/include/rlib/LICENSE
new file mode 100644
index 0000000..b11a017
--- /dev/null
+++ b/nemu/include/rlib/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-2018 Recolic Keghart <root@recolic.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/nemu/include/rlib/Makefile b/nemu/include/rlib/Makefile
new file mode 100644
index 0000000..1587264
--- /dev/null
+++ b/nemu/include/rlib/Makefile
@@ -0,0 +1,33 @@
+CXX ?= g++
+CC ?= gcc
+AR ?= ar
+CXXFLAGS = -O3 -std=c++14 -fPIC
+CFLAGS = 
+ARFLAGS = rcs
+
+PREFIX ?= /usr
+
+def:
+	@echo Run make install
+
+install_header:
+	[ ! -d $(PREFIX)/include/rlib ] || rm -rf $(PREFIX)/include/rlib
+	cp -r . $(PREFIX)/include/rlib
+	rm -rf $(PREFIX)/include/rlib/test $(PREFIX)/include/rlib/.git
+
+install_cmake:
+	[ ! -d $(PREFIX)/lib/cmake/rlib ] || rm -rf $(PREFIX)/lib/cmake/rlib
+	[ ! -d $(PREFIX)/lib/cmake ] || cp -r cmake $(PREFIX)/lib/cmake/rlib
+
+install: install_header install_cmake
+
+uninstall:
+	rm -rf $(PREFIX)/include/rlib $(PREFIX)/lib/cmake/rlib
+
+clean:
+
+.PHONY: test
+
+test:
+	cd test && ./test.sh
+
diff --git a/nemu/include/rlib/README.md b/nemu/include/rlib/README.md
new file mode 100644
index 0000000..13c9e78
--- /dev/null
+++ b/nemu/include/rlib/README.md
@@ -0,0 +1,20 @@
+# rlib
+
+[![CodeFactor](https://www.codefactor.io/repository/github/recolic/rlib/badge/master)](https://www.codefactor.io/repository/github/recolic/rlib/overview/master)
+![AWS CodeBuild](https://codebuild.us-west-1.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiVUEvK3oxVFAzMlZuZkJlSFE1L1VWSU9IWDBmK0ZpRGZ2clArTDE2UTk4QUZNS1RLUEp2K0lVaVBmNmZjWHNpOXZpRktlOU5RV3k0TjNWcHFKVmVwelJFPSIsIml2UGFyYW1ldGVyU3BlYyI6IllnZUwzWndPSEN4NTFPeGoiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
+
+Here is recolic's private library...
+
+# TODO
+
+```c++
+RETEST rlib::noncopyable
+rlib::stdio fd control is still a problem.
+
+rlib::meta::print_constexpr
+rlib::meta::array
+rlib::meta::array::to_tuple
+rlib::meta::string
+
+#DONE#rlib::logger
+```
diff --git a/nemu/include/rlib/buildspec.yaml b/nemu/include/rlib/buildspec.yaml
new file mode 100644
index 0000000..a138100
--- /dev/null
+++ b/nemu/include/rlib/buildspec.yaml
@@ -0,0 +1,17 @@
+version: 0.2
+
+phases:
+  install:
+    run-as: root
+    commands:
+      - make install
+  pre_build:
+    commands:
+      - g++ --version
+      - clang++ --version
+      - icpc --version
+  build:
+    commands:
+      - make
+      - make test
+
diff --git a/nemu/include/rlib/c-with-class.h b/nemu/include/rlib/c-with-class.h
new file mode 100644
index 0000000..4a45bc5
--- /dev/null
+++ b/nemu/include/rlib/c-with-class.h
@@ -0,0 +1,27 @@
+#ifndef RLIB_CWITHCLASS_H_
+#define RLIB_CWITHCLASS_H_
+
+//TODO: clean namespace.
+//TODO: use macro to type class_name only once.
+//#error c_with_class not completed yet
+
+#ifdef __cplusplus
+#error You should not use c-with-class.h in real C++.
+#endif
+
+#define RCPP_NEW(type,name,constructor_arg) struct type name __attribute__((cleanup(type##_rcpp_destructor)));type##_rcpp_constructor(&name,constructor_arg)
+#define RCPP_CALL(i_objectname,i_funcname, ...) i_objectname.i_funcname(&i_objectname, ##__VA_ARGS__) //ONLY static public function can be called directly!!!
+#define RCPP_PCALL(p_objectname,i_funcname, ...) p_objectname->i_funcname(p_objectname, ##__VA_ARGS__)
+
+#define RCPP_CLASS_DECL(class_name) struct class_name;
+#define RCPP_CLASS_METHOD_EXTERN_DECL(class_name, method_name, return_type, ...) typedef return_type (* class_name##method_name##_rcpp_t)(struct class_name *this, ##__VA_ARGS__); //VAARGS is `int arg1, float arg2, ...`
+#define RCPP_CLASS_BEGIN(class_name) struct class_name {
+#define RCPP_CLASS_METHOD_DECL(class_name, method_name, ...) RCPP_CLASS_MEMBER_DECL(class_name##method_name##_rcpp_t, method_name)
+#define RCPP_CLASS_MEMBER_DECL(type, name) type name;
+#define RCPP_CLASS_END() };
+#define RCPP_CLASS_METHOD_IMPL(class_name, method_name, return_type, ...) return_type class_name##method_name##_rcpp_impl(struct class_name *this, ##__VA_ARGS__) //VAARGS is `int arg1, float arg2, ...`
+#define RCPP_CLASS_CONSTRUCTOR_IMPL(class_name) void class_name##_rcpp_constructor(struct class_name *this, void *arg) //TODO: Register all methods.
+#define RCPP_CLASS_METHOD_REGISTER(class_name, method_name) this->method_name = &class_name##method_name##_rcpp_impl;
+#define RCPP_CLASS_DESTRUCTOR_IMPL(class_name) void class_name##_rcpp_destructor(struct class_name *this)
+
+#endif
diff --git a/nemu/include/rlib/class_decorator.hpp b/nemu/include/rlib/class_decorator.hpp
new file mode 100644
index 0000000..16492af
--- /dev/null
+++ b/nemu/include/rlib/class_decorator.hpp
@@ -0,0 +1,47 @@
+#ifndef RLIB_CLASS_DECO_HPP_
+#define RLIB_CLASS_DECO_HPP_
+
+#include <rlib/require/cxx11>
+
+namespace rlib {
+    namespace _noncp_ {
+        class noncopyable
+        {
+        public:
+            noncopyable() = default;
+            ~noncopyable() = default;
+            noncopyable(const noncopyable &) = delete;
+            noncopyable &operator=(const noncopyable &) = delete;
+        };
+    }
+    typedef _noncp_::noncopyable noncopyable;
+}
+
+namespace rlib {
+    namespace _nonmv_ {
+        class nonmovable : private noncopyable
+        {
+        public:
+            nonmovable() = default;
+            ~nonmovable() = default;
+            nonmovable(const nonmovable &&) = delete;
+            nonmovable &operator=(const nonmovable &&) = delete;
+        };
+    }
+    typedef _nonmv_::nonmovable nonmovable;
+}
+
+namespace rlib {
+    namespace _nonconstructible_ {
+        class nonconstructible : private rlib::nonmovable
+        {
+        public:
+            nonconstructible() = delete;
+            ~nonconstructible() = delete;
+        };
+    }
+    typedef _nonconstructible_::nonconstructible nonconstructible;
+    typedef nonconstructible static_class;
+}
+
+#endif
\ No newline at end of file
diff --git a/nemu/include/rlib/cmake/CMakeLists.txt b/nemu/include/rlib/cmake/CMakeLists.txt
new file mode 100644
index 0000000..a5e8307
--- /dev/null
+++ b/nemu/include/rlib/cmake/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Use this file if you want to include rlib as a subdirectory
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    # using clang
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+    set(rlib_CXX_FLAGS "-Wno-terminate")
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+    # using Visual Studio C++
+endif()
+
+if(MSYS OR MINGW)
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+endif()
+
+include_directories(..)
+
diff --git a/nemu/include/rlib/cmake/cmake.include b/nemu/include/rlib/cmake/cmake.include
new file mode 100644
index 0000000..88b4897
--- /dev/null
+++ b/nemu/include/rlib/cmake/cmake.include
@@ -0,0 +1,15 @@
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    # using clang
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+    set(rlib_CXX_FLAGS "-Wno-terminate")
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+    # using Visual Studio C++
+endif()
+
+if(MSYS OR MINGW)
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+endif()
+
+
diff --git a/nemu/include/rlib/cmake/rlib-config.cmake b/nemu/include/rlib/cmake/rlib-config.cmake
new file mode 100644
index 0000000..0cc3a3c
--- /dev/null
+++ b/nemu/include/rlib/cmake/rlib-config.cmake
@@ -0,0 +1,17 @@
+# use this file if you want to install rlib
+
+set(rlib_INCLUDE_DIRS ${PREFIX}/include)
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    # using clang
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+    set(rlib_CXX_FLAGS "-Wno-terminate")
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+    # using Visual Studio C++
+endif()
+
+if(MINGW)
+    add_definitions(-DRLIB_MINGW_DISABLE_TLS)
+endif()
diff --git a/nemu/include/rlib/functional.hpp b/nemu/include/rlib/functional.hpp
new file mode 100644
index 0000000..c14bc9b
--- /dev/null
+++ b/nemu/include/rlib/functional.hpp
@@ -0,0 +1,125 @@
+#ifndef RLIB_FUNCTIONAL_HPP_
+#define RLIB_FUNCTIONAL_HPP_
+
+#include <rlib/require/cxx17>
+#include <rlib/class_decorator.hpp>
+#include <rlib/sys/os.hpp>
+
+#include <type_traits>
+#include <list>
+#include <functional>
+#include <chrono>
+
+namespace rlib {
+    namespace impl {
+        template <typename Func, typename... Args>
+        struct repeated_func {
+            using return_type = typename std::invoke_result<Func, Args ...>::type;
+            auto operator ()(size_t count, Func f, Args ... args) {
+                for(size_t cter = 0; cter < count - 1; ++cter)
+                    f(std::forward<Args>(args) ...);
+                return f(std::forward<Args>(args) ...);
+            }
+        };
+        template <typename Func, typename... Args>
+        struct repeated_func_return_list {
+            using return_type = typename std::invoke_result<Func, Args ...>::type;
+            auto operator ()(size_t count, Func f, Args ... args) {
+                std::list<return_type> ret;
+                if(count == 0) return ret;
+                for(size_t cter = 0; cter < count; ++cter)
+                    ret.push_back(std::move(f(std::forward<Args>(args) ...)));
+                return ret;
+            }
+        };
+
+    }
+}
+
+namespace rlib {
+    template <class Func, typename... Args>
+    constexpr static inline double timeof(Func && f, Args && ... args)
+    {
+        auto begin = std::chrono::high_resolution_clock::now();
+        f(std::forward<Args>(args) ...);
+        auto end = std::chrono::high_resolution_clock::now();
+        return ::std::chrono::duration<double>(end - begin).count(); 
+    }
+
+    template <class Func, typename... Args>
+    constexpr static inline auto repeat(size_t count, Func && f, Args && ... args)
+    {
+        // Unnecessary asserts for debugging.
+        using return_type = typename std::invoke_result<Func, Args ...>::type;
+        using return_type2 = typename std::invoke_result<typename impl::repeated_func<Func, Args ...>, size_t, Func, Args ...>::type;
+        using return_type3 = decltype(impl::repeated_func<Func, Args ...>()(count, f, args ...));
+        static_assert(std::is_same<return_type, return_type2>::value);
+        static_assert(std::is_same<return_type, return_type3>::value);
+
+        if(count == 0)
+            throw std::invalid_argument("Can not repeat for zero times.");
+
+        return std::bind(impl::repeated_func<Func, Args ...>(), count, std::forward<Func>(f), std::forward<Args>(args) ...);
+    }
+    template <class Func, typename... Args>
+    constexpr static inline auto repeat_and_return_list(size_t count, Func f, Args... args)
+    {
+        return std::bind(impl::repeated_func_return_list<Func, Args ...>(), count, std::forward<Func>(f), std::forward<Args>(args) ...);
+    }
+}
+
+namespace std {
+#if RLIB_CXX_STD >= 2017
+    class execution;
+#endif
+}
+
+// functools here.
+#if 0 // not finished
+#include <algorithm>
+namespace rlib {
+    template <Iterable buffer_t>
+    class wrappedIterable : public buffer_t {
+    public:
+        using buffer_t::buffer_t;
+        using buffer_type = buffer_t;
+        using value_type = buffer_t::value_type;
+        using this_type = wrappedIterable<buffer_t>;
+        wrappedIterable(const buffer_t &b) : buffer_t(b) {}
+        wrappedIterable(buffer_t &&b) : buffer_t(std::forward<buffer_t>(b)) {}
+
+#if RLIB_CXX_STD >= 2017
+        // std::foreach wrapper
+        this_type &map(std::execution &&policy, std::function<value_type(const value_type &)> mapper_func) {
+            std::for_each(std::forward<std::execution>(policy), begin, end, [&mapper_func](value_type &v){v = mapper_func(v);});
+        }
+        this_type &map(std::execution &&policy, std::function<void(value_type &)> mapper_func) {
+            std::for_each(std::forward<std::execution>(policy), begin, end, mapper_func);
+        }
+
+
+#endif
+        // std::foreach wrapper
+        this_type &map(std::function<value_type(const value_type &)> mapper_func) {
+            std::for_each(begin, end, [&mapper_func](value_type &v){v = mapper_func(v);});
+            return *this;
+        }
+        this_type &map(std::function<void(value_type &)> mapper_func) {
+            std::for_each(begin, end, mapper_func);
+            return *this;
+        }
+
+        this_type &filter(std::function<bool(const value_type &)> filter_func) {
+            std::remove_if(begin, end, [&filter_func](const value_type &v) -> bool {return !filter_func(v);});
+            return *this;
+        }
+
+        this_type &flat_map(std::function<buffer_type<value_type>(const value_type &)>) {
+
+        }
+
+    };
+}
+#endif
+
+#endif
diff --git a/nemu/include/rlib/impl/traceable_list.hpp b/nemu/include/rlib/impl/traceable_list.hpp
new file mode 100644
index 0000000..053f4bb
--- /dev/null
+++ b/nemu/include/rlib/impl/traceable_list.hpp
@@ -0,0 +1,225 @@
+#ifndef _RLIB_IMPL_TRACEABLE_LIST_HPP
+#define _RLIB_IMPL_TRACEABLE_LIST_HPP 1
+
+#include <list>
+#include <stdexcept>
+#include <utility>
+
+namespace rlib {
+    namespace impl {
+        // A double linked list with ability to get iterator from data_t*. Designed for *_object_pool.
+        // Only implement few necessary functionalibities.
+        template<typename T, typename extra_info_t>
+        class traceable_list {
+            struct node {
+                /*
+                 * You may not manage data ownness here. Or you must carefully check if (node*)&data works.
+                 */
+                T data; // Able to get iterator from T*
+                node *prev;
+                node *next;
+                extra_info_t extra_info; // bool flag. specially designed for object_pool.
+                uint32_t magic = 0x19980427;
+                template <typename... TConstructArgs>
+                node(node *prev, node *next, const extra_info_t &extra_info, TConstructArgs... args) 
+                    : data(std::forward<TConstructArgs>(args) ...), prev(prev), next(next), extra_info(extra_info)
+                {}
+            };
+
+        public:
+            class iterator : std::bidirectional_iterator_tag {
+                friend class traceable_list;
+
+            public:
+                using pointer = T *;
+                using reference = T &;
+                explicit iterator(node *ptr) : ptr(ptr) {}
+
+                explicit iterator(T *data_pointer) : ptr(reinterpret_cast<node *>(data_pointer)) {
+                    if (ptr->magic != 0x19980427)
+                        throw std::invalid_argument(
+                                "magic_num verification failed. invalid data_pointer passed or ruined memory?");
+                }
+
+                T &operator*() {
+                    // If this is an iterator to empty_list.begin(), then nullptr->data throws.
+                    return ptr->data;
+                }
+
+                T *operator->() {
+                    // If this is an iterator to empty_list.begin(), then nullptr->data throws.
+                    return &ptr->data;
+                }
+
+                extra_info_t &get_extra_info() {
+                    return ptr->extra_info;
+                }
+
+                const T &operator*() const {
+                    // If this is an iterator to empty_list.begin(), then nullptr->data throws.
+                    return ptr->data;
+                }
+
+                const T *operator->() const {
+                    // If this is an iterator to empty_list.begin(), then nullptr->data throws.
+                    return &ptr->data;
+                }
+
+                const extra_info_t &get_extra_info() const {
+                    return ptr->extra_info;
+                }
+
+                iterator &operator++() {
+                    ptr = ptr->next;
+                    return *this;
+                }
+
+                const iterator operator++(int) {
+                    iterator backup(ptr);
+                    operator++();
+                    return std::move(backup);
+                }
+
+                iterator &operator--() {
+                    if (!ptr && _impl_tail)
+                        ptr = _impl_tail;
+                    else
+                        ptr = ptr->prev;
+                    return *this;
+                }
+
+                const iterator operator--(int) {
+                    iterator backup(ptr);
+                    operator--();
+                    return std::move(backup);
+                }
+
+                bool operator==(const iterator &another) const {
+                    return ptr == another.ptr;
+                }
+
+                bool operator!=(const iterator &another) const {
+                    return !operator==(another);
+                }
+
+            private:
+                node *ptr;
+
+                iterator(node *ptr, node *tail) : ptr(ptr), _impl_tail(tail) {}
+
+                node *_impl_tail = nullptr; // If this iter is created by begin() or end(), it must set this ptr to support end().operator--(), to indicate that this iterator is not invalid.
+            };
+
+            ~traceable_list() {
+                for (auto iter = begin(); iter != end();) {
+                    auto to_release = iter++;
+                    delete to_release.ptr;
+                }
+            }
+
+            iterator begin() {
+                return iterator(head, tail);
+            }
+
+            iterator end() {
+                return iterator((node *) nullptr, tail);
+            }
+
+            template <typename... ConstructArgs>
+            void emplace_one(const iterator &where, const extra_info_t &extra_info, ConstructArgs... constructArgs) {
+                auto new_node = new node(nullptr, where.ptr, extra_info, std::forward<ConstructArgs>(constructArgs) ...);
+                ++m_size;
+                if (!head) {
+                    tail = head = new_node;
+                    return;
+                };
+                auto ptr = where.ptr;
+                if (!ptr) {
+                    // is end();
+                    tail->next = new_node;
+                    new_node->prev = tail;
+
+                    tail = new_node;
+                    return;
+                }
+                auto left = ptr->prev, right = ptr;
+                new_node->prev = right->prev;
+                if (left) left->next = new_node;
+                right->prev = new_node;
+
+                if (head == ptr)
+                    head = new_node;
+            }
+
+            void push_one(const iterator &where, T &&data, const extra_info_t &extra_info) {
+                emplace_one(where, extra_info, std::forward<T>(data));
+            }
+
+            void push_one(const iterator &where, const T &data, const extra_info_t &extra_info) {
+                T _data(data);
+                push_one(where, std::move(_data), extra_info);
+            }
+
+            void push_back(T &&data, const extra_info_t &extra_info) {
+                push_one(end(), std::forward<T>(data), extra_info);
+            }
+
+            void push_back(const T &data, const extra_info_t &extra_info) {
+                push_one(end(), std::forward<T>(data), extra_info);
+            }
+
+            void push_front(T &&data, const extra_info_t &extra_info) {
+                push_one(begin(), std::forward<T>(data), extra_info);
+            }
+
+            void push_front(const T &data, const extra_info_t &extra_info) {
+                push_one(begin(), std::forward<T>(data), extra_info);
+            }
+
+            void pop_one(const iterator &which) {
+                if (!head)
+                    throw std::invalid_argument("nothing to pop.");
+                auto ptr = which.ptr;
+                if (!ptr) {
+                    // end()
+                    throw std::invalid_argument("you may not pop end().");
+                }
+                auto left = ptr->prev, right = ptr->next;
+
+                if (left) left->next = right;
+                if (right) right->prev = left;
+                if (head == ptr)
+                    head = right;
+                if (tail == ptr)
+                    tail = left;
+                --m_size;
+                delete which.ptr;
+            }
+
+            void pop_front() {
+                pop_one(begin());
+            }
+
+            void pop_back() {
+                pop_one(--end());
+            }
+
+            void pop_some(const iterator &from, const iterator &to) {
+                for (auto iter = from; iter != to;) {
+                    auto to_pop = iter++;
+                    pop_one(to_pop);
+                }
+            }
+
+            size_t size() {
+                return m_size;
+            }
+
+        private:
+            node *head = nullptr;
+            node *tail = nullptr;
+            size_t m_size = 0;
+        };
+    }
+}
+#endif // _RLIB_IMPL_TRACEABLE_LIST_HPP
diff --git a/nemu/include/rlib/log.hpp b/nemu/include/rlib/log.hpp
new file mode 100644
index 0000000..10b6bab
--- /dev/null
+++ b/nemu/include/rlib/log.hpp
@@ -0,0 +1,188 @@
+#ifndef RLIB_LOG_HPP_
+#define RLIB_LOG_HPP_ 1
+
+#include <string>
+#include <fstream>
+#include <list>
+#include <climits>
+#include <rlib/sys/os.hpp>
+#include <rlib/stdio.hpp>
+#include <rlib/sys/time.hpp>
+#include <rlib/class_decorator.hpp>
+
+// currently disable this error-prone shit.
+#define RLIB_IMPL_ENABLE_LOGGER_FROM_FD 0
+
+#ifndef RLIB_IMPL_ENABLE_LOGGER_FROM_FD
+#include <rlib/sys/fd.hpp>
+#if RLIB_OS_ID != OS_UNKNOWN
+#   if RLIB_COMPILER_ID == CC_GCC
+#       include <ext/stdio_filebuf.h>
+#       define RLIB_IMPL_ENABLE_LOGGER_FROM_FD 1
+#   elif RLIB_COMPILER_ID == CC_MSVC
+#       define RLIB_IMPL_ENABLE_LOGGER_FROM_FD 1
+#   endif
+#endif
+#endif
+
+#ifdef ERROR
+#pragma message (": warning MSVC_Macro_pollution: You MUST NOT define the macro `ERROR`. I've undefined it here.")
+#undef ERROR
+#endif
+
+namespace rlib {
+    using namespace rlib::literals;
+
+    // Allow extension.
+    enum class log_level_t : int { FATAL = 1, ERROR, WARNING, INFO, VERBOSE, DEBUG };
+    namespace impl {
+        inline int &max_predefined_log_level() {
+            static int instance = (int)log_level_t::DEBUG;
+            return instance;
+        }
+    }
+    /*
+    How to update log_level_t:
+        Extend `enum log_level_t ...`
+        Modify libr.cc:`max_predefined_log_level ...`
+        Add an RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND
+        Append logger::predefined_log_level_name
+    */
+
+    class logger : rlib::noncopyable {
+    public:
+        logger() = delete;
+        logger(std::ostream &stream) : pstream(&stream) {}
+        logger(const std::string &file_name) : pstream(new std::ofstream(file_name, std::ios::out)), 
+            must_delete_stream_as_ofstream(true) {
+                if(!dynamic_cast<std::ofstream &>(*pstream))
+                    throw std::runtime_error("Failed to open file {}."_format(file_name));
+            }
+        logger(logger &&another) : pstream(another.pstream), 
+            custom_log_level_names(std::move(another.custom_log_level_names)),
+            log_level(another.log_level),
+            must_delete_stream_as_ofstream(another.must_delete_stream_as_ofstream),
+            enable_flush(another.enable_flush)
+            {another.must_delete_stream_as_ofstream = false;}
+        ~logger() {
+            if(must_delete_stream_as_ofstream)
+                delete dynamic_cast<std::ofstream *>(pstream);
+        }
+
+        logger &operator=(logger &&another) {
+            pstream = another.pstream;
+            enable_flush = another.enable_flush;
+            must_delete_stream_as_ofstream = another.must_delete_stream_as_ofstream;
+            log_level = another.log_level;
+            custom_log_level_names = std::move(another.custom_log_level_names);
+            another.must_delete_stream_as_ofstream = false;
+            return *this;
+        }
+        
+#if RLIB_IMPL_ENABLE_LOGGER_FROM_FD == 1
+#if RLIB_OS_ID != OS_UNKNOWN
+        logger(fd file_descriptor_or_handle)
+#   if RLIB_COMPILER_ID == CC_GCC
+        : _gcc_filebuf(file_descriptor_or_handle, std::ios::out), _gcc_real_stream(&_gcc_filebuf), 
+            stream(_gcc_real_stream) {}
+#   elif RLIB_COMPILER_ID == CC_MSVC
+        : _msvc_real_stream(::_fdopen(file_descriptor_or_handle, "w")), 
+            stream(_msvc_real_stream) {}
+#   endif
+#endif
+#endif
+
+        void set_log_level(log_level_t max_level) {
+            this->log_level = max_level;
+        }
+        void set_flush(bool enable_flush) noexcept {
+            this->enable_flush = enable_flush;
+        }
+        template <typename ... Args>
+        void log(log_level_t level, const std::string &info, Args ... extra_args) const {
+            if(is_predefined_log_level(level) && level > this->log_level)
+                return;
+            (*pstream) << "[{}|{}] {}"_format(get_current_time_str(), log_level_name(level), impl::format_string(info, std::forward<Args>(extra_args) ...)) << RLIB_IMPL_ENDLINE;
+            if(enable_flush)
+                pstream->flush();
+        }
+        // Warning: this method is not thread-safe.
+        log_level_t register_log_level(const std::string &name) {
+            if(impl::max_predefined_log_level() == INT_MAX)
+                throw std::overflow_error("At most {}(INT_MAX) log_level is allowed."_format(INT_MAX));
+            ++ impl::max_predefined_log_level();
+            log_level_t new_level = (log_level_t)impl::max_predefined_log_level();
+            custom_log_level_names.push_back({new_level, name});
+            return new_level;
+        }
+
+#define RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(_name, _enum_name) template <typename ... Args> void _name(const std::string &info, Args ... extra) const { \
+            log(log_level_t::_enum_name, info, std::forward<Args>(extra) ...); }
+
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(fatal, FATAL)
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(error, ERROR)
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(warning, WARNING)
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(info, INFO)
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(verbose, VERBOSE)
+        RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND(debug, DEBUG)
+
+#undef RLIB_IMPL_MACRO_LOG_ADD_SHORTHAND
+
+    private:
+        static constexpr const char * predefined_log_level_name(log_level_t level) noexcept {
+            switch(level) {
+            case log_level_t::FATAL:
+                return "FATAL";
+            case log_level_t::ERROR:
+                return "ERROR";
+            case log_level_t::WARNING:
+                return "WARNING";
+            case log_level_t::INFO:
+                return "INFO";
+            case log_level_t::VERBOSE:
+                return "VERBOSE";
+            case log_level_t::DEBUG:
+                return "DEBUG";
+            default:
+                return "";
+            }
+        }
+        static constexpr bool is_predefined_log_level(log_level_t level) noexcept {
+            return predefined_log_level_name(level)[0] != '\0';
+        }
+        std::string log_level_name(log_level_t level) const noexcept {
+            std::string name = predefined_log_level_name(level);
+            if(!name.empty())
+                return name;
+            for(const auto &level_and_name : custom_log_level_names) {
+                if(level == level_and_name.first) {
+                    name = level_and_name.second;
+                    break;
+                }
+            }
+            if(!name.empty())
+                return name;
+            name = "LEVEL-";
+            name += std::to_string((int)level);
+            return name;
+        }
+
+        std::ostream *pstream;
+
+        std::list<std::pair<log_level_t, std::string> > custom_log_level_names;
+        log_level_t log_level = log_level_t::INFO; // `Ignore` deadline.
+
+        bool must_delete_stream_as_ofstream = false;
+        bool enable_flush = true;
+#if RLIB_IMPL_ENABLE_LOGGER_FROM_FD == 1
+#   if RLIB_COMPILER_ID == CC_GCC
+        __gnu_cxx::stdio_filebuf<char> _gcc_filebuf;
+        std::ostream _gcc_real_stream;
+#   elif RLIB_COMPILER_ID == CC_MSVC
+        std::ofstream _msvc_real_stream;
+#   endif
+#endif
+    };
+}
+
+#endif
diff --git a/nemu/include/rlib/macro.hpp b/nemu/include/rlib/macro.hpp
new file mode 100644
index 0000000..c411790
--- /dev/null
+++ b/nemu/include/rlib/macro.hpp
@@ -0,0 +1,34 @@
+#ifndef R_MACRO_HPP
+#define R_MACRO_HPP
+
+#ifdef RLIB_EMPTY_MACRO
+#undef RLIB_EMPTY_MACRO
+#endif
+#define RLIB_EMPTY_MACRO
+
+#ifndef RLIB_MACRO_DECAY
+#define RLIB_MACRO_DECAY(m) (m)
+#endif
+
+#ifndef _RLIB_MACRO_ENSTRING
+#define _RLIB_MACRO_ENSTRING(_s) #_s
+#endif
+
+#ifndef RLIB_MACRO_TO_CSTR
+#define RLIB_MACRO_TO_CSTR(m) _RLIB_MACRO_ENSTRING(m)
+#endif
+
+//#ifndef RLIB_MACRO_EQL
+//#define RLIB_MACRO_EQL(a, b) (RLIB_MACRO_TO_CSTR(a) == RLIB_MACRO_TO_CSTR(b))
+//#endif
+
+#ifndef RLIB_MACRO_CAT
+#define RLIB_MACRO_CAT(a, b) _RLIB_MACRO_CAT_I(a, b)
+#define _RLIB_MACRO_CAT_I(a, b) _RLIB_MACRO_CAT_II(~, a ## b)
+#define _RLIB_MACRO_CAT_II(p, res) res
+#endif
+#ifndef RLIB_MAKE_UNIQUE_NAME
+#define RLIB_MAKE_UNIQUE_NAME(base) RLIB_MACRO_CAT(base, __COUNTER__)
+#endif
+
+#endif
diff --git a/nemu/include/rlib/meta.hpp b/nemu/include/rlib/meta.hpp
new file mode 100644
index 0000000..e14e460
--- /dev/null
+++ b/nemu/include/rlib/meta.hpp
@@ -0,0 +1,59 @@
+#ifndef RLIB_MEelement_typeA_HPP_
+#define RLIB_MEelement_typeA_HPP_
+
+#include <rlib/sys/os.hpp>
+#include <cstddef> // size_t
+#include <tuple>
+
+namespace rlib {
+    #if RLIB_CXX_STD >= 2017
+    namespace impl {
+        template <auto first_ele, auto... _>
+        struct array_first_ele_type_impl { using type = decltype(first_ele); };
+    }
+    template <auto... arr>
+    struct meta_array {
+        using this_type = typename ::rlib::meta_array<arr ...>;
+        using element_type = typename ::rlib::impl::array_first_ele_type_impl<arr...>::type;
+
+        template <size_t index>
+        struct at_last {
+            static constexpr auto value() noexcept {
+                return at_last_impl<index, arr ...>::value();
+            }
+            constexpr operator element_type() {
+                return at_last<index>::value();
+            }
+        };
+        
+        template <size_t index>
+        struct at {
+            static constexpr auto value() {
+                return at_last<sizeof...(arr) - index - 1>::value();
+            }
+            constexpr operator element_type() {
+                return at<index>::value();
+            }
+        };
+
+        static constexpr auto to_tuple() {
+            return std::make_tuple(arr ...);
+        }
+
+    private:
+        template <size_t index, auto first_ele, auto... _arr>
+        struct at_last_impl {
+            static constexpr auto value() {
+                if constexpr(sizeof...(_arr) == index)
+                    return first_ele;
+                else
+                    return at_last_impl<index, _arr ...>::value();
+            }
+        };
+    };
+    #endif
+
+    template <size_t... forwardedArgs> struct argForwarder {};
+}
+
+#endif
diff --git a/nemu/include/rlib/opt.hpp b/nemu/include/rlib/opt.hpp
new file mode 100644
index 0000000..7ea0e29
--- /dev/null
+++ b/nemu/include/rlib/opt.hpp
@@ -0,0 +1,126 @@
+/*
+This opt_parser works well for correct cmd args, 
+but not guaranteed to works well in all condition
+(for example, some ill formed argument).
+
+It's possible to read wrong information rather than
+raise an exception on some rare ill formed arguments.
+*/
+#ifndef R_OPT_HPP
+#define R_OPT_HPP
+
+#include <rlib/require/cxx14>
+#include <rlib/class_decorator.hpp>
+#include <rlib/string.hpp>
+#include <rlib/scope_guard.hpp>
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+
+namespace rlib {
+    class opt_parser : private noncopyable
+    {
+    public:
+        opt_parser() = delete;
+        opt_parser(size_t arglen, char **argv) {
+            if(argv[0] == nullptr)
+                throw std::runtime_error("Invalid argv passed to rlib::opt_parser. argv[0] is nullptr.");
+            arg0 = argv[0];
+            for(size_t cter = 1; cter < arglen; ++cter)
+                args.push_back(std::string(argv[cter]));
+        }
+
+        rlib::string getSubCommand() {
+            if(args.empty())
+                throw std::runtime_error("No sub-command available.");
+            auto cmd = std::move(args[0]);
+            args.erase(args.begin());
+            return std::move(cmd);
+        }
+
+        rlib::string getSubCommand(const std::string &def) {
+            if(args.empty())
+                return def;
+            auto cmd = std::move(args[0]);
+            args.erase(args.begin());
+            return std::move(cmd);
+        }
+
+        rlib::string getSelf() {
+            return arg0;
+        }
+
+        rlib::string getValueArg(const std::string &argName, bool required = true, const std::string &def = std::string())
+        { //If required argument not exist, I'll throw. Else, return "" if arg is not read.
+            using rlib::literals::operator "" _format;
+            bool useEqualSym = false;
+            auto pos = std::find_if(args.cbegin(), args.cend(), [&](auto &ele)->bool{
+                if(ele == argName) return true;
+                if(ele.size() > argName.size() && ele.substr(0, argName.size()+1) == argName + "=") {
+                    useEqualSym = true;
+                    return true;
+                }
+                return false;
+            });
+            if(required && pos == args.cend())
+                throw std::invalid_argument("Required argument '{}' not provided."_format(argName));
+            if(pos == args.cend())
+                return std::move(def);
+            rlib_defer(([&, pos]{if(!useEqualSym) args.erase(pos+1); args.erase(pos);}));
+            if(useEqualSym)
+                return pos->substr(argName.size() + 1);
+            else
+            {
+                if(++pos == args.cend())
+                    throw std::invalid_argument("Argument '{}' must provide value."_format(argName));
+                return *pos;
+            }
+        }
+
+        rlib::string getValueArg(const std::string &longName, const char *shortName)
+        { //getValueArg("--long", "-l") may be converted to getValueArg("--long", true).
+            return getValueArg(longName, shortName, true);
+        }
+
+        bool getBoolArg(const std::string &argName)
+        { //Return if it's defined.
+            auto pos = std::find(args.cbegin(), args.cend(), argName);
+            if(pos == args.cend()) return false;
+            args.erase(pos);
+            return true;
+        }
+
+        rlib::string getValueArg(const std::string &longName, const std::string &shortName, bool required = true, const std::string &def = std::string())
+        {
+            using rlib::literals::operator "" _format;
+            std::string valueL = getValueArg(longName, false);
+            std::string valueS = getValueArg(shortName, false);
+            
+            const std::string &value = valueL.empty() ? valueS : valueL;
+            if(value.empty()) {
+                if(required)
+                    throw std::invalid_argument("Required argument '{}/{}' not provided."_format(longName, shortName));
+                else
+                    return def;
+            }
+            return std::move(value);
+        }
+
+        bool getBoolArg(const std::string &longName, const std::string &shortName)
+        {
+            return getBoolArg(longName) || getBoolArg(shortName);
+        }
+
+        bool allArgDone() const
+        {
+            return args.empty();
+        }
+    private:
+        std::vector<std::string> args;
+        std::string arg0;
+    };
+}
+
+#endif
diff --git a/nemu/include/rlib/pool.hpp b/nemu/include/rlib/pool.hpp
new file mode 100644
index 0000000..dca2665
--- /dev/null
+++ b/nemu/include/rlib/pool.hpp
@@ -0,0 +1,129 @@
+#ifndef _RLIB_OBJ_POOL_HPP
+#define _RLIB_OBJ_POOL_HPP 1
+
+#include <rlib/impl/traceable_list.hpp>
+#include <rlib/class_decorator.hpp>
+#include <utility>
+#include <tuple>
+#include <functional>
+#include <algorithm>
+
+#ifdef RLIB_SWITCH_USE_MINGW_THREAD_FIX
+#include <mingw.mutex.h>
+#include <mingw.thread.h>
+#include <mingw.condition_variable.h>
+#else
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#endif
+
+namespace rlib {
+    /*
+     * Multi-threaded object_pool. It will block current thread and wait if
+     *     borrow_one() starves, until some other threads release their obj.
+     */
+    template<typename obj_t, typename... _bound_construct_args_t>
+    class fixed_object_pool : rlib::nonmovable {
+    protected:
+        using element_t = obj_t;
+        using buffer_t = impl::traceable_list<obj_t, bool>;
+        using this_type = fixed_object_pool<obj_t, _bound_construct_args_t ...>;
+    public:
+        explicit fixed_object_pool(size_t max_size, _bound_construct_args_t ... _args)
+                : max_size(max_size), _bound_args(std::forward<_bound_construct_args_t>(_args) ...) 
+        {}
+
+        void fill_full() {
+            for (size_t cter = 0; cter < max_size; ++cter) {
+                new_obj_to_buffer();
+                free_list.push_back(&*--buffer.end());
+            }
+        }
+
+        // `new` an object. Return nullptr if pool is full.
+        obj_t *try_borrow_one() {
+            std::lock_guard<std::mutex> _l(buffer_mutex);
+            return do_try_borrow_one();
+        }
+        obj_t *borrow_one() {
+            auto result = try_borrow_one();
+            if(result)
+                return result;
+            // Not available. Wait for release_one.
+            std::unique_lock<std::mutex> lk(buffer_mutex);
+
+            borrow_cv.wait(lk, [this]{return this->new_obj_ready;});
+
+            result = do_try_borrow_one();
+            lk.unlock();
+            if(!result)
+                throw std::logic_error("unknown par error.");
+            return result;
+        }
+        void release_one(obj_t *which) {
+            {
+                std::lock_guard<std::mutex> _l(buffer_mutex);
+                free_list.push_front(which);
+                typename buffer_t::iterator elem_iter(which);
+                elem_iter.get_extra_info() = true; // mark as free.
+                new_obj_ready = true;
+            } // lock released.
+            borrow_cv.notify_one();
+        }
+
+        void reconstruct_one(obj_t *which) {
+            reconstruct_impl(which, std::make_index_sequence<sizeof...(_bound_construct_args_t)>());
+        }
+
+    protected:
+        buffer_t buffer; // list<obj_t obj, bool is_free>
+    private:
+        std::tuple<_bound_construct_args_t ...> _bound_args;
+
+        size_t max_size;
+        std::list<obj_t *> free_list;
+        std::mutex buffer_mutex;
+        std::condition_variable borrow_cv;
+        volatile bool new_obj_ready = false;
+
+        // try_borrow_one without lock.
+        obj_t *do_try_borrow_one() {
+            // Optimize here if is performance bottleneck (lockless list... etc...)
+            borrow_again:
+            if (free_list.size() > 0) {
+                // Some object is free. Just return one.
+                obj_t *result = *free_list.begin();
+                free_list.pop_front();
+
+                typename buffer_t::iterator elem_iter(result);
+                elem_iter.get_extra_info() = false; // mark as busy.
+                new_obj_ready = false;
+                return result;
+            }
+            if (buffer.size() < max_size) {
+                new_obj_to_buffer();
+                free_list.push_back(&*--buffer.end());
+                goto borrow_again;
+            }
+            return nullptr;
+        }
+
+        // fake emplace_back
+        template<size_t ... index_seq>
+        inline void new_obj_to_buffer_impl(std::index_sequence<index_seq ...>) {
+            buffer.emplace_one(buffer.end(), true, std::get<index_seq>(_bound_args) ...);
+        }
+        template<size_t ... index_seq>
+        inline void reconstruct_impl(obj_t *which, std::index_sequence<index_seq ...>) {
+            which->~obj_t();
+            new(which) obj_t(std::get<index_seq>(_bound_args) ...);
+        }
+
+        inline void new_obj_to_buffer() {
+            new_obj_to_buffer_impl(std::make_index_sequence<sizeof...(_bound_construct_args_t)>());
+        }
+    };
+}
+
+#endif
diff --git a/nemu/include/rlib/require/cxx11 b/nemu/include/rlib/require/cxx11
new file mode 100644
index 0000000..2565010
--- /dev/null
+++ b/nemu/include/rlib/require/cxx11
@@ -0,0 +1,12 @@
+#ifndef R_CXX11_REQUIRED
+#define R_CXX11_REQUIRED
+
+#include <rlib/sys/os.hpp>
+
+#if RLIB_CXX_STD <= 1997
+#error This file requires compiler and library support \
+for the ISO C++ 2011 standard. This support must be enabled \
+with the -std=c++11 or -std=gnu++11 compiler options.
+#endif
+
+#endif
diff --git a/nemu/include/rlib/require/cxx14 b/nemu/include/rlib/require/cxx14
new file mode 100644
index 0000000..17e676c
--- /dev/null
+++ b/nemu/include/rlib/require/cxx14
@@ -0,0 +1,12 @@
+#ifndef R_CXX14_REQUIRED
+#define R_CXX14_REQUIRED
+
+#include <rlib/sys/os.hpp>
+
+#if RLIB_CXX_STD <= 2011
+#error This file requires compiler and library support \
+for the ISO C++ 2014 standard. This support must be enabled \
+with the -std=c++14 or -std=gnu++14 compiler options.
+#endif
+
+#endif
diff --git a/nemu/include/rlib/require/cxx17 b/nemu/include/rlib/require/cxx17
new file mode 100644
index 0000000..d201616
--- /dev/null
+++ b/nemu/include/rlib/require/cxx17
@@ -0,0 +1,13 @@
+#ifndef R_CXX17_REQUIRED
+#define R_CXX17_REQUIRED
+
+#include <rlib/sys/os.hpp>
+
+#if RLIB_CXX_STD <= 2014
+#error This file requires compiler and library support \
+for the ISO C++ 2017 standard. This support must be enabled \
+with the -std=c++17, -std=gnu++17, -std=c++1z, -std=gnu++1z \
+compiler options.
+#endif
+
+#endif
diff --git a/nemu/include/rlib/scope_guard.hpp b/nemu/include/rlib/scope_guard.hpp
new file mode 100644
index 0000000..58ea5cf
--- /dev/null
+++ b/nemu/include/rlib/scope_guard.hpp
@@ -0,0 +1,100 @@
+/* Exception safe usage:
+ *
+ * reinforce_scope_begin(_gname, [](){do_sth();})
+ * do_something();
+ * reinforce_scope_end(_gname)
+ *
+ */
+
+#ifndef R_SCOPE_GUARD
+#define R_SCOPE_GUARD
+
+#include <rlib/require/cxx11>
+#include <functional>
+#include <rlib/class_decorator.hpp>
+
+namespace rlib {
+    class scope_guard : private noncopyable
+    {
+    public: 
+        template<class Callable> 
+        scope_guard(Callable && undo_func) : f(std::forward<Callable>(undo_func)) {}
+
+        scope_guard(scope_guard && other) : f(std::move(other.f)) {
+            other.f = nullptr;
+        }
+
+        ~scope_guard() {
+            if(f) f(); // must not throw
+        }
+
+        void dismiss() noexcept {
+            f = nullptr;
+        }
+
+        void force_call() noexcept {
+            if(f) f();
+            dismiss();
+        }
+
+    private:
+        std::function<void()> f;
+    };
+}
+
+
+#ifndef rlib_defer
+#include <rlib/macro.hpp>
+#define rlib_defer(callable) ::rlib::scope_guard RLIB_MAKE_UNIQUE_NAME(_guarder_id_) (callable)
+#endif
+
+#define RLIB_reinforce_scope_begin(guarderName, callable) scope_guard guarderName = callable; try{
+#define RLIB_reinforce_scope_end(guarderName) } catch(...) { guarderName.force_call(); throw;}
+
+/*
+scope_guards scope_exit, scope_fail;
+
+action1();
+scope_exit += []{ cleanup1(); };
+scope_fail += []{ rollback1(); };
+
+action2();
+scope_exit += []{ cleanup2(); };
+scope_fail += []{ rollback2(); };
+
+do_something();
+
+scope_fail.dismiss();
+*/
+
+#include <deque>
+
+namespace rlib {
+    class scope_guards : private noncopyable
+    {
+    public:
+        template<class Callable>
+        scope_guards& operator += (Callable && undo_func) {
+            fbuf.emplace_front(std::forward<Callable>(undo_func));
+            return *this;
+        }
+
+        ~scope_guards() {
+            force_call();
+        }
+
+        void dismiss() noexcept {
+            fbuf.clear();
+        }
+
+        void force_call() noexcept {
+            for(auto &f : fbuf) f();
+            dismiss();
+        }
+    private:
+        std::deque<std::function<void(void)> > fbuf;
+    };
+}
+
+
+#endif
diff --git a/nemu/include/rlib/stdio.hpp b/nemu/include/rlib/stdio.hpp
new file mode 100644
index 0000000..80d6e6b
--- /dev/null
+++ b/nemu/include/rlib/stdio.hpp
@@ -0,0 +1,243 @@
+/*
+ *
+ * stdio wrapper for modern c++: python like print/println/printf/printfln
+ *                               print_iter println_iter
+ * Recolic Keghart <root@recolic.net>
+ * MIT License
+ *
+ */
+
+#ifndef R_STDIO_HPP
+#define R_STDIO_HPP
+
+#include <rlib/require/cxx11> // Use fold expression if cxx17 is available.
+#include <rlib/sys/os.hpp> // Enable inline variable if cxx17 is available.
+#include <string>
+#include <iostream>
+#include <rlib/string.hpp> // format_string
+#include <type_traits>
+
+#if RLIB_OS_ID == OS_WINDOWS
+#define RLIB_IMPL_ENDLINE "\r\n"
+#elif RLIB_OS_ID == OS_MACOS
+#define RLIB_IMPL_ENDLINE "\r"
+#else
+#define RLIB_IMPL_ENDLINE "\n"
+#endif
+
+namespace rlib {
+    namespace impl {
+        template <typename T>
+        struct print_wrapper {
+            print_wrapper() = delete;
+            print_wrapper(const T &dat)
+                : wrapper(dat) {}
+
+            const T &wrapper;
+
+            friend std::ostream & operator<< (std::ostream &os, print_wrapper<T> p) {
+                return os << p.wrapper;
+            }
+        };
+    }
+}
+
+namespace rlib {
+// print to custom stream
+    template <typename PrintFinalT>
+    void print(std::ostream &os, PrintFinalT reqArg);
+    template <typename Required, typename... Optional>
+    void print(std::ostream &os, Required reqArgs, Optional... optiArgs);
+    template <typename... Optional>
+    void println(std::ostream &os, Optional... optiArgs);
+    template <>
+    void println(std::ostream &os);
+
+    template <typename Iterable, typename Printable>
+    void print_iter(std::ostream &os, Iterable arg, Printable spliter);
+    template <typename Iterable, typename Printable>
+    void println_iter(std::ostream &os, Iterable arg, Printable spliter);
+    template <typename Iterable>
+    void print_iter(std::ostream &os, Iterable arg);
+    template <typename Iterable>
+    void println_iter(std::ostream &os, Iterable arg);
+
+    template <typename... Args>
+    size_t printf(std::ostream &os, const std::string &fmt, Args... args);
+    template <typename... Args>
+    size_t printfln(std::ostream &os, const std::string &fmt, Args... args);
+
+    inline rlib::string scanln(std::istream &is = std::cin, char delimiter = '\n') noexcept {
+        std::string line;
+        std::getline(is, line, delimiter);
+        return std::move(line);
+    }
+
+    // default for std::cout
+    template <typename... Args>
+    void println(Args... args);
+    template <>
+    void println();
+    template <typename... Args>
+    void print(Args... args);
+    template <typename Iterable, typename Printable>
+    void print_iter(Iterable arg, Printable spliter);
+    template <typename Iterable, typename Printable>
+    void println_iter(Iterable arg, Printable spliter);
+    template <typename Iterable>
+    void print_iter(Iterable arg);
+    template <typename Iterable>
+    void println_iter(Iterable arg);
+    template <typename... Args>
+    size_t printf(const std::string &fmt, Args... args);
+    template <typename... Args>
+    size_t printfln(const std::string &fmt, Args... args);
+
+    // implementations below --------------------------------
+
+    namespace impl {
+        inline bool &enable_endl_flush() {
+            static bool instance = true;
+            return instance;
+        }
+    }
+
+    inline bool sync_with_stdio(bool sync = true) noexcept {
+        return std::ios::sync_with_stdio(sync);
+    }
+    inline bool enable_endl_flush(bool enable = true) noexcept {
+        return impl::enable_endl_flush() = enable;
+    }
+
+// Implements.
+    template < class CharT, class Traits >
+    inline std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os) {
+        os << RLIB_IMPL_ENDLINE;
+        if(impl::enable_endl_flush())
+            os.flush();
+        return os;
+    }
+
+    // With custom os
+    template <typename PrintFinalT>
+    void print(std::ostream &os, PrintFinalT reqArg)
+    {
+        os << reqArg;
+    }
+    template <typename Required, typename... Optional>
+    void print(std::ostream &os, Required reqArgs, Optional... optiArgs)
+    {
+        os << reqArgs << ' ';
+        print(os, optiArgs ...);
+    }
+    template <typename... Optional>
+    void println(std::ostream &os, Optional... optiArgs)
+    {
+        print(os, optiArgs ...);
+        println(os);
+    }
+    template <> 
+    inline void println(std::ostream &os)
+    {
+        os << rlib::endl;
+    }
+
+    template <typename Iterable, typename Printable>
+    void print_iter(std::ostream &os, Iterable arg, Printable spliter)
+    {
+        for(const auto & i : arg)
+            os << i << spliter;
+    }
+    template <typename Iterable, typename Printable>
+    void println_iter(std::ostream &os, Iterable arg, Printable spliter)
+    {
+        print_iter(os, arg, spliter);
+        println(os);
+    }
+    template <typename Iterable>
+    void print_iter(std::ostream &os, Iterable arg)
+    {
+        print_iter(os, arg, ' ');
+    }
+    template <typename Iterable>
+    void println_iter(std::ostream &os, Iterable arg)
+    {
+        println_iter(os, arg, ' ');
+    }
+
+    template <typename... Args>
+    size_t printf(std::ostream &os, const std::string &fmt, Args... args)
+    {
+        std::string to_print = impl::format_string(fmt, args...); 
+        print(os, to_print);
+        return to_print.size();
+    }
+    template <typename... Args>
+    size_t printfln(std::ostream &os, const std::string &fmt, Args... args)
+    {
+        size_t len = printf(os, fmt, args...);
+        println(os);
+        return len + 1;
+    }
+
+
+
+    // default for std::cout
+    template <typename... Args>
+    void println(Args... args) {
+        return println(std::cout, std::forward<Args>(args) ...);
+    }
+    template <>
+    inline void println() {
+        return println(std::cout);
+    }
+    template <typename... Args>
+    void print(Args... args) {
+        return print(std::cout, std::forward<Args>(args) ...);
+    }
+    template <typename Iterable, typename Printable>
+    void print_iter(Iterable arg, Printable spliter) {
+        return print_iter(std::cout, std::forward<Iterable>(arg), spliter);
+    }
+    template <typename Iterable, typename Printable>
+    void println_iter(Iterable arg, Printable spliter) {
+        return println_iter(std::cout, std::forward<Iterable>(arg), spliter);
+    }
+    template <typename Iterable>
+    void print_iter(Iterable arg) {
+        return print_iter(std::cout, std::forward<Iterable>(arg));
+    }
+    template <typename Iterable>
+    void println_iter(Iterable arg) {
+        return println_iter(std::cout, std::forward<Iterable>(arg));
+    }
+    template <typename... Args>
+    size_t printf(const std::string &fmt, Args... args) {
+        return printf(std::cout, fmt, std::forward<Args>(args) ...);
+    }
+    template <typename... Args>
+    size_t printfln(const std::string &fmt, Args... args) {
+        return printfln(std::cout, fmt, std::forward<Args>(args) ...);
+    }
+
+
+    // If the stream is stringstream or ostringstream,
+    //   it will fails to match print(ostream &, args...),
+    //   and match print(args ...). It leads to an error.
+    // Here's the fallback on such sucking substitution error.
+    template <typename StreamType, typename... Args>
+    void println(StreamType &os, Args... args) {
+        using ostream_or_data = typename std::conditional<std::is_base_of<std::ostream, StreamType>::value, 
+            std::ostream &, impl::print_wrapper<StreamType>>::type;
+        return println(static_cast<ostream_or_data>(os), std::forward<Args>(args) ...);
+    }
+    template <typename StreamType, typename... Args>
+    void print(StreamType &os, Args... args) {
+        using ostream_or_data = typename std::conditional<std::is_base_of<std::ostream, StreamType>::value, 
+            std::ostream &, impl::print_wrapper<StreamType>>::type;
+        return print(static_cast<ostream_or_data>(os), std::forward<Args>(args) ...);
+    }
+}
+
+
+#endif
diff --git a/nemu/include/rlib/stream.hpp b/nemu/include/rlib/stream.hpp
new file mode 100644
index 0000000..93f77c2
--- /dev/null
+++ b/nemu/include/rlib/stream.hpp
@@ -0,0 +1,24 @@
+#include <rlib/require/cxx11>
+#include <streambuf>
+#include <iostream>
+#include <rlib/sys/os.hpp>
+
+namespace rlib {
+    namespace impl {
+        class NullStreamBuf : public std::streambuf
+        {
+        public:
+            int overflow(int c) { return c; }
+        };
+
+        inline NullStreamBuf & null_streambuf() {
+            static NullStreamBuf instance;
+            return instance;
+        }
+    }
+    
+    inline std::ostream &null_stream() {
+        static std::ostream instance(impl::null_streambuf());
+        return instance;
+    }
+}
diff --git a/nemu/include/rlib/string.hpp b/nemu/include/rlib/string.hpp
new file mode 100644
index 0000000..9fe7968
--- /dev/null
+++ b/nemu/include/rlib/string.hpp
@@ -0,0 +1,410 @@
+/*
+ *
+ * string.hpp: string process utility.
+ * Recolic Keghart <root@recolic.net>
+ * MIT License
+ *
+ */
+
+#ifndef R_STRING_HPP
+#define R_STRING_HPP
+
+#include <rlib/require/cxx14>
+#include <rlib/class_decorator.hpp>
+#include <rlib/sys/os.hpp>
+
+#include <array>
+#include <vector>
+#include <string>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <stdexcept>
+#include <sstream>
+#include <type_traits>
+
+// Intel C++ compiler has a pending bug for `thread_local inline` variable.
+#if RLIB_COMPILER_ID == CC_ICC
+#define RLIB_IMPL_SSTREAM_DISABLE_TLS
+#endif
+
+#if RLIB_COMPILER_IS_MINGW
+#define RLIB_IMPL_SSTREAM_DISABLE_TLS
+#endif
+
+namespace rlib {
+    // literals::_format, format_string, string::format
+    namespace impl {
+#ifndef RLIB_IMPL_SSTREAM_DISABLE_TLS
+        inline std::stringstream &to_string_by_sstream_ss() {
+            static thread_local std::stringstream instance;
+            return instance;
+        }
+        inline std::stringstream &_format_string_helper_ss() {
+            static thread_local std::stringstream instance;
+            return instance;
+        }
+#endif
+        template <typename VarT>
+        std::string to_string_by_sstream(VarT &thing) {
+#if defined(RLIB_IMPL_SSTREAM_DISABLE_TLS)
+            // Fix intel C++ bug https://software.intel.com/en-us/forums/intel-c-compiler/topic/784136
+            // Also fix mingw bug. But much slower!
+            std::stringstream ss;
+#else
+            auto &ss = to_string_by_sstream_ss();
+            ss.str(std::string());
+#endif
+            ss << thing;
+            return ss.str();
+        }
+
+        template<typename... Args>
+        std::string _format_string_helper(const std::string &fmt, Args... args) {
+#if defined(RLIB_IMPL_SSTREAM_DISABLE_TLS)
+            // Fix intel C++ bug https://software.intel.com/en-us/forums/intel-c-compiler/topic/784136
+            std::stringstream ss;
+#else
+            auto &ss = _format_string_helper_ss(); // cached stringstream is much quicker.
+            ss.str(std::string());
+#endif
+            size_t pos = 0, prev_pos = 0;
+            std::array<std::string, sizeof...(args)> argsArr{to_string_by_sstream(args) ...};
+            size_t current_used_arg = 0;
+            bool discovered_escape_char = false;
+            while((pos = fmt.find("{}", pos)) != std::string::npos) {
+                if(pos != 0 && fmt[pos-1] == '\\') {
+                    // Invalid hit.
+                    discovered_escape_char = true;
+                    pos += 2;
+                }
+                else {
+                    std::string cutted_tmp_str = fmt.substr(prev_pos, pos - prev_pos);
+                    if(discovered_escape_char) {
+                        // hand-written string replace. Replace `\{}` to `{}`.
+                        size_t pos = 0;
+                        while((pos = cutted_tmp_str.find("\\{}", pos)) != std::string::npos) {
+                            cutted_tmp_str.erase(pos, 1);
+                            pos += 2;
+                        }
+                    }
+                    if(current_used_arg >= sizeof...(args)) {
+                        // not enough arguments.
+                        throw std::out_of_range("format_string: not enough arguments for format string `" + fmt +
+                            "`. Expecting at least " + std::to_string(current_used_arg+1) + ", got " + 
+                            std::to_string(sizeof...(args)));
+                    }
+                    ss << cutted_tmp_str << argsArr.at(current_used_arg);
+                    pos += 2;
+                    prev_pos = pos;
+                    ++current_used_arg;
+                }
+            }
+            if(current_used_arg != sizeof...(args)) {
+                // too many arguments.
+                throw std::out_of_range("format_string: too many arguments for format string `" + fmt +
+                    "`. Expecting " + std::to_string(current_used_arg) + ", got " + 
+                    std::to_string(sizeof...(args)));
+            }
+            ss << fmt.substr(prev_pos);
+            return ss.str();
+        }
+        template<typename... Args>
+        inline std::string format_string(const std::string &fmt, Args... args) {
+            return _format_string_helper(fmt, args...);
+        }
+        //template<>
+        //inline std::string format_string<>(const std::string &fmt) {
+        //    return fmt;
+        //}
+ 
+        /*
+        template<class MetaFmtArr, typename... Args>
+        constexpr std::string format_string_meta(Args... args) {
+            return (args + ...);
+        }*/
+    }
+
+    // format_string_c, string::cformat
+    namespace impl {
+        inline char *_format_string_c_helper(const char *fmt, ...)
+        {
+            int n;
+            int size = std::strlen(fmt);
+            char *p, *np;
+            va_list ap;
+
+            if ((p = (char *)malloc(size)) == NULL)
+                throw std::runtime_error("malloc returns null.");
+
+            while (1) {
+                va_start(ap, fmt);
+                n = vsnprintf(p, size, fmt, ap);
+                va_end(ap);
+
+                if (n < 0)
+                    throw std::runtime_error("vsnprintf returns " + std::to_string(n));
+                if (n < size)
+                    return p;
+
+                size = n + 1;
+
+                if ((np = (char *)realloc (p, size)) == NULL) {
+                    free(p);
+                    throw std::runtime_error("make_message realloc failed.");
+                } else {
+                    p = np;
+                }
+            }
+        }
+        template<typename... Args>
+        std::string format_string_c(const std::string &fmt, Args... args)
+        {
+            char *res = _format_string_c_helper(fmt.c_str(), args ...);
+            std::string s = res;
+            free(res);
+            return s;
+        }
+    }
+
+    class string : public std::string {
+    public:
+        using std::string::string;
+        string() : std::string() {}
+        string(const std::string &s) : std::string(s) {}
+        string(std::string &&s) : std::string(std::forward<std::string>(s)) {}
+
+    private:
+        template <typename T> struct as_helper {};
+        template <typename T>
+        T as(as_helper<T>) const {
+            if(empty()) return T();
+            return T(*this);
+        }
+        const char *as(as_helper<const char *>) const {
+            return this->c_str();
+        }
+        std::string as(as_helper<std::string>) const {
+            return std::move(*this);
+        }
+        rlib::string as(as_helper<rlib::string>) const {
+            return std::move(*this);
+        }
+        char as(as_helper<char>) const {
+            if(size() > 1)
+                throw std::invalid_argument("Can not convert rlib::string to char: size() > 1.");
+            return size() == 0 ? '\0' : *cbegin();
+        }
+        // unsigned-char conflicts with uint8_t. I'll regard it as uint8_t. ("8".as<unsigned char> == 8)
+        //unsigned char as(as_helper<unsigned char>) const {
+        //    return static_cast<unsigned char>(as<char>());
+        //}
+        bool as(as_helper<bool>) const {
+            if(*this == "true") {
+                return true;
+            }
+            else if(*this == "false") {
+                return false;
+            }
+            // Nothing is slower than throw(); Just test more cases...
+            else if(*this == "1" || *this == "True" || *this == "TRUE") {
+                return true;
+            }
+            else if(*this == "0" || *this == "False" || *this == "FALSE") {
+                return false;
+            }
+            throw std::invalid_argument("Can not convert rlib::string to bool. Not matching any template.");
+        }
+
+#define RLIB_IMPL_GEN_AS_NUMERIC(type, std_conv) \
+        type as(as_helper<type>) const { \
+            if(empty()) return 0; \
+            return std::std_conv(*this); \
+        }
+
+        RLIB_IMPL_GEN_AS_NUMERIC(int, stoi)
+        RLIB_IMPL_GEN_AS_NUMERIC(long, stol)
+        RLIB_IMPL_GEN_AS_NUMERIC(unsigned long, stoul)
+        RLIB_IMPL_GEN_AS_NUMERIC(unsigned long long, stoull)
+        RLIB_IMPL_GEN_AS_NUMERIC(long long, stoll)
+        RLIB_IMPL_GEN_AS_NUMERIC(float, stof)
+        RLIB_IMPL_GEN_AS_NUMERIC(double, stod)
+        RLIB_IMPL_GEN_AS_NUMERIC(long double, stold)
+
+#define RLIB_IMPL_GEN_AS_ALIAS(new_type, old_type) \
+        new_type as(as_helper<new_type>) const { \
+            return static_cast<new_type>(as<old_type>()); \
+        }
+
+        RLIB_IMPL_GEN_AS_ALIAS(unsigned int, unsigned long)
+        RLIB_IMPL_GEN_AS_ALIAS(unsigned short, unsigned long)
+        RLIB_IMPL_GEN_AS_ALIAS(uint8_t, unsigned long)
+
+        RLIB_IMPL_GEN_AS_ALIAS(short, int)
+        RLIB_IMPL_GEN_AS_ALIAS(int8_t, int)
+
+    public:
+        template <typename T>
+        T as() const {
+            return std::forward<T>(as(as_helper<T>()));
+        }
+
+        std::vector<string> split(const char &divider = ' ') const {
+            const string &toSplit = *this;
+            std::vector<string> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(toSplit.substr(prev, curr - prev));
+                ++curr; // skip divider
+                prev = curr;
+            }
+            buf.push_back(toSplit.substr(prev));
+            return buf;
+        }
+        std::vector<string> split(const std::string &divider) const {
+            const string &toSplit = *this;
+            std::vector<string> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(toSplit.substr(prev, curr - prev));
+                curr += divider.size(); // skip divider
+                prev = curr;
+            }
+            buf.push_back(toSplit.substr(prev));
+            return buf;
+        }
+        template <typename T>
+        std::vector<T> split_as(const char &divider = ' ') const {
+            const string &toSplit = *this;
+            std::vector<T> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());
+                ++curr; // skip divider
+                prev = curr;
+            }
+            buf.push_back(string(toSplit.substr(prev)).as<T>());
+            return std::move(buf);
+        }
+        template <typename T>
+        std::vector<T> split_as(const std::string &divider) const {
+            const string &toSplit = *this;
+            std::vector<T> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());
+                curr += divider.size(); // skip divider
+                prev = curr;
+            }
+            buf.push_back(string(toSplit.substr(prev)).as<T>());
+            return std::move(buf);
+        }
+
+        template <class ForwardIterable>
+        string &join(const ForwardIterable &buffer) {
+            join(buffer.cbegin(), buffer.cend());
+            return *this;
+        }
+        template <class ForwardIterator>
+        string &join(ForwardIterator begin, ForwardIterator end) {
+            const string &toJoin = *this;
+            std::string result;
+            for(ForwardIterator iter = begin; iter != end; ++iter) {
+                if(iter != begin)
+                    result += toJoin;
+                result += *iter;
+            }
+            return operator=(std::move(result));
+        }
+
+        string &strip() {
+            strip(" \t\r\n");
+            return *this;
+        }
+        template <typename CharOrStringOrView>
+        string &strip(const CharOrStringOrView &stripped) {
+            size_t len = size();
+            size_t begin = find_first_not_of(stripped);
+
+            if(begin == std::string::npos) {
+                clear();
+                return *this;
+            }
+            size_t end = find_last_not_of(stripped);
+
+            erase(end + 1, len - end - 1);
+            erase(0, begin);
+            return *this;
+        }
+
+        string &replace(const std::string &from, const std::string &to) {
+            size_t _;
+            replace(from, to, _);
+            return *this;
+        }
+        string &replace(const std::string &from, const std::string &to, size_t &out_times) {
+            if(from.empty())
+                return *this;
+            size_t start_pos = 0;
+            size_t times = 0;
+            while((start_pos = find(from, start_pos)) != std::string::npos)
+            {
+                ++times;
+                this->std::string::replace(start_pos, from.length(), to);
+                start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
+            }
+            out_times = times;
+            return *this;
+        }
+        string &replace_once(const std::string &from, const std::string &to) {
+            bool _;
+            replace_once(from, to, _);
+            return *this;
+        }
+        string &replace_once(const std::string &from, const std::string &to, bool &out_replaced) {
+            size_t start_pos = find(from);
+            if(start_pos == std::string::npos) {
+                out_replaced = false;
+            }
+            else {
+                this->std::string::replace(start_pos, from.length(), to);
+                out_replaced = true;
+            }
+            return *this;
+        }
+
+        template <typename... Args>
+        string &format(Args... args) {
+            return operator=(std::move(impl::format_string(*this, args ...)));
+        }
+        template <typename... Args>
+        string &cformat(Args... args) {
+            return operator=(std::move(impl::format_string_c(*this, args ...)));
+        }
+    };
+
+    namespace impl {
+        struct formatter {
+            formatter(const std::string &fmt) : fmt(fmt) {}
+            formatter(std::string &&fmt) : fmt(fmt) {}
+            template <typename... Args>
+            std::string operator ()(Args... args) {
+                return std::move(rlib::impl::format_string(fmt, args ...));
+            }
+
+            std::string fmt;
+        };
+    }
+
+    namespace literals {
+        inline impl::formatter operator "" _format (const char *str, size_t) {
+            return impl::formatter(str);
+        }
+        inline rlib::string operator "" _rs (const char *str, size_t len) {
+            return rlib::string(str, len);
+        }
+    }
+}
+
+#endif
diff --git a/nemu/include/rlib/sys/cc_codegen.py b/nemu/include/rlib/sys/cc_codegen.py
new file mode 100755
index 0000000..35dcc8f
--- /dev/null
+++ b/nemu/include/rlib/sys/cc_codegen.py
@@ -0,0 +1,43 @@
+#!/bin/env python3
+
+rlib_cc_magic = 90713
+def getSerialNumber():
+    global rlib_cc_magic
+    rlib_cc_magic += 1
+    return rlib_cc_magic
+
+def genDefList(idarr):
+    s = '#if'
+    cter = 1
+    for i in idarr:
+        s += ' defined(' + i + ')'
+        if cter != len(idarr):
+            s += ' ||'
+        cter += 1
+    return s
+
+print('// Generated by cc_codegen.py. Do not edit it by hand.')
+
+with open("cc_list") as fd:
+    osarr=fd.read().split('\n')
+    for i in osarr:
+        if i == '':
+            continue
+        if i[0] == '#':
+            continue
+        iarr=i.split(' ')
+        if len(iarr) < 2:
+            continue
+        print('#ifndef RLIB_COMPILER_ID')
+        print(genDefList(iarr[:-1:]))
+        print('#define RLIB_COMPILER_ID', 'CC_' + iarr[-1])
+        print('#endif')
+        print('#endif')
+        print('#define CC_' + iarr[-1], getSerialNumber())
+        print('')
+
+print('#ifndef RLIB_COMPILER_ID')
+print('#define RLIB_COMPILER_ID CC_UNKNOWN')
+print('#endif')
+print('#define CC_UNKNOWN', getSerialNumber())
+
diff --git a/nemu/include/rlib/sys/cc_list b/nemu/include/rlib/sys/cc_list
new file mode 100644
index 0000000..92d6817
--- /dev/null
+++ b/nemu/include/rlib/sys/cc_list
@@ -0,0 +1,71 @@
+_ACC_ ACC
+__CMB__ ALTIUM_MICROBLAZE
+__CHC__ ALTIUM_HARDWARE
+__ACK__ AMSTERDAM
+__CC_ARM ARMCC
+AZTEC_C __AZTEC_C__ AZTEC
+__BORLANDC__ __CODEGEARC__ BORLAND
+__CC65__ CC65
+__clang__ CLANG
+__COMO__ COMEAU
+__DECC __DECCXX COMPAQ
+__convexc__ CONVEX
+__COMPCERT__ COMPCERT
+__COVERITY__ COVERITY
+_CRAYC CRAY
+__DCC__ DIAB
+_DICE DICE
+__DMC__ DIGITAL_MARS
+__SYSC__ DIGNUS
+__DJGPP__ DJGPP
+__ICC __INTEL_COMPILER ICC
+# ICC must be placed before: EDG, GCC
+__EDG__ EDG
+__PATHCC__ EKOPATH
+__FCC_VERSION FUJITSU
+__GNUC__ GCC
+__ghs__ GREENHILL
+__HP_cc HPC
+__HP_aCC HPACXX
+__IAR_SYSTEMS_ICC__ IARC
+__IBMCPP__ __IBMC__ IBMC
+__IMAGECRAFT__ IMAGECRAFT
+__KCC KAICXX
+__CA__ __KEIL__ KEIL_CARM
+__C166__ KEIL_C166
+__C51__ __CX51__ KEIL_C51
+__LCC__ LCC
+__llvm__ LLVM
+__MWERKS__ __CWCC__ METROWERKS
+_MSC_VER MSVC
+_MRI MICROTEC
+__NDPC__ __NDPX__ MICROWAY
+__sgi sgi MIPSPRO
+MIRACLE MIRACLE
+__MRC__ MPW_C MPW_CPLUS MPW
+__CC_NORCROFT NORCROFT
+__NWCC__ NWCC
+__OPEN64__ __OPENCC__ OPEN64
+ORA_PROC ORACLE_PROC
+__SUNPRO_C __SUNPRO_CC SOLARIS
+__PACIFIC__ PACIFIC
+_PACC_VER PLAM
+__POCC__ PELLES
+__PGI PORTLAND
+__RENESAS__ __HITACHI__ RENESAS
+SASC __SASC __SASC__ SASC
+_SCO_DS SCO_OPENSERVER
+SDCC SDCC
+__SNC__ SN
+__VOSC__ STRATUS_VOS
+__SC__ SYMANTEC
+__TenDRA__ TENDRA
+__TI_COMPILER_VERSION__ _TMS320C6X TEXAS
+THINKC3 THINKC4 THINK
+__TINYC__ TINYC
+__TURBOC__ TURBOC
+_UCC UCC
+__USLC__ USLC
+__VBCC__ VBCC
+__WATCOMC__ WATCOM
+__ZTC__ ZORTECH
diff --git a/nemu/include/rlib/sys/compiler_detector b/nemu/include/rlib/sys/compiler_detector
new file mode 100644
index 0000000..99f6dcf
--- /dev/null
+++ b/nemu/include/rlib/sys/compiler_detector
@@ -0,0 +1,495 @@
+// Generated by cc_codegen.py. Do not edit it by hand.
+#ifndef RLIB_COMPILER_ID
+#if defined(_ACC_)
+#define RLIB_COMPILER_ID CC_ACC
+#endif
+#endif
+#define CC_ACC 90714
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CMB__)
+#define RLIB_COMPILER_ID CC_ALTIUM_MICROBLAZE
+#endif
+#endif
+#define CC_ALTIUM_MICROBLAZE 90715
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CHC__)
+#define RLIB_COMPILER_ID CC_ALTIUM_HARDWARE
+#endif
+#endif
+#define CC_ALTIUM_HARDWARE 90716
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__ACK__)
+#define RLIB_COMPILER_ID CC_AMSTERDAM
+#endif
+#endif
+#define CC_AMSTERDAM 90717
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CC_ARM)
+#define RLIB_COMPILER_ID CC_ARMCC
+#endif
+#endif
+#define CC_ARMCC 90718
+
+#ifndef RLIB_COMPILER_ID
+#if defined(AZTEC_C) || defined(__AZTEC_C__)
+#define RLIB_COMPILER_ID CC_AZTEC
+#endif
+#endif
+#define CC_AZTEC 90719
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__BORLANDC__) || defined(__CODEGEARC__)
+#define RLIB_COMPILER_ID CC_BORLAND
+#endif
+#endif
+#define CC_BORLAND 90720
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CC65__)
+#define RLIB_COMPILER_ID CC_CC65
+#endif
+#endif
+#define CC_CC65 90721
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__clang__)
+#define RLIB_COMPILER_ID CC_CLANG
+#endif
+#endif
+#define CC_CLANG 90722
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__COMO__)
+#define RLIB_COMPILER_ID CC_COMEAU
+#endif
+#endif
+#define CC_COMEAU 90723
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__DECC) || defined(__DECCXX)
+#define RLIB_COMPILER_ID CC_COMPAQ
+#endif
+#endif
+#define CC_COMPAQ 90724
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__convexc__)
+#define RLIB_COMPILER_ID CC_CONVEX
+#endif
+#endif
+#define CC_CONVEX 90725
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__COMPCERT__)
+#define RLIB_COMPILER_ID CC_COMPCERT
+#endif
+#endif
+#define CC_COMPCERT 90726
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__COVERITY__)
+#define RLIB_COMPILER_ID CC_COVERITY
+#endif
+#endif
+#define CC_COVERITY 90727
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_CRAYC)
+#define RLIB_COMPILER_ID CC_CRAY
+#endif
+#endif
+#define CC_CRAY 90728
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__DCC__)
+#define RLIB_COMPILER_ID CC_DIAB
+#endif
+#endif
+#define CC_DIAB 90729
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_DICE)
+#define RLIB_COMPILER_ID CC_DICE
+#endif
+#endif
+#define CC_DICE 90730
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__DMC__)
+#define RLIB_COMPILER_ID CC_DIGITAL_MARS
+#endif
+#endif
+#define CC_DIGITAL_MARS 90731
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__SYSC__)
+#define RLIB_COMPILER_ID CC_DIGNUS
+#endif
+#endif
+#define CC_DIGNUS 90732
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__DJGPP__)
+#define RLIB_COMPILER_ID CC_DJGPP
+#endif
+#endif
+#define CC_DJGPP 90733
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+#define RLIB_COMPILER_ID CC_ICC
+#endif
+#endif
+#define CC_ICC 90734
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__EDG__)
+#define RLIB_COMPILER_ID CC_EDG
+#endif
+#endif
+#define CC_EDG 90735
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__PATHCC__)
+#define RLIB_COMPILER_ID CC_EKOPATH
+#endif
+#endif
+#define CC_EKOPATH 90736
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__FCC_VERSION)
+#define RLIB_COMPILER_ID CC_FUJITSU
+#endif
+#endif
+#define CC_FUJITSU 90737
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__GNUC__)
+#define RLIB_COMPILER_ID CC_GCC
+#endif
+#endif
+#define CC_GCC 90738
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__ghs__)
+#define RLIB_COMPILER_ID CC_GREENHILL
+#endif
+#endif
+#define CC_GREENHILL 90739
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__HP_cc)
+#define RLIB_COMPILER_ID CC_HPC
+#endif
+#endif
+#define CC_HPC 90740
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__HP_aCC)
+#define RLIB_COMPILER_ID CC_HPACXX
+#endif
+#endif
+#define CC_HPACXX 90741
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__IAR_SYSTEMS_ICC__)
+#define RLIB_COMPILER_ID CC_IARC
+#endif
+#endif
+#define CC_IARC 90742
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__IBMCPP__) || defined(__IBMC__)
+#define RLIB_COMPILER_ID CC_IBMC
+#endif
+#endif
+#define CC_IBMC 90743
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__IMAGECRAFT__)
+#define RLIB_COMPILER_ID CC_IMAGECRAFT
+#endif
+#endif
+#define CC_IMAGECRAFT 90744
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__KCC)
+#define RLIB_COMPILER_ID CC_KAICXX
+#endif
+#endif
+#define CC_KAICXX 90745
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CA__) || defined(__KEIL__)
+#define RLIB_COMPILER_ID CC_KEIL_CARM
+#endif
+#endif
+#define CC_KEIL_CARM 90746
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__C166__)
+#define RLIB_COMPILER_ID CC_KEIL_C166
+#endif
+#endif
+#define CC_KEIL_C166 90747
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__C51__) || defined(__CX51__)
+#define RLIB_COMPILER_ID CC_KEIL_C51
+#endif
+#endif
+#define CC_KEIL_C51 90748
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__LCC__)
+#define RLIB_COMPILER_ID CC_LCC
+#endif
+#endif
+#define CC_LCC 90749
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__llvm__)
+#define RLIB_COMPILER_ID CC_LLVM
+#endif
+#endif
+#define CC_LLVM 90750
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__MWERKS__) || defined(__CWCC__)
+#define RLIB_COMPILER_ID CC_METROWERKS
+#endif
+#endif
+#define CC_METROWERKS 90751
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_MSC_VER)
+#define RLIB_COMPILER_ID CC_MSVC
+#endif
+#endif
+#define CC_MSVC 90752
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_MRI)
+#define RLIB_COMPILER_ID CC_MICROTEC
+#endif
+#endif
+#define CC_MICROTEC 90753
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__NDPC__) || defined(__NDPX__)
+#define RLIB_COMPILER_ID CC_MICROWAY
+#endif
+#endif
+#define CC_MICROWAY 90754
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__sgi) || defined(sgi)
+#define RLIB_COMPILER_ID CC_MIPSPRO
+#endif
+#endif
+#define CC_MIPSPRO 90755
+
+#ifndef RLIB_COMPILER_ID
+#if defined(MIRACLE)
+#define RLIB_COMPILER_ID CC_MIRACLE
+#endif
+#endif
+#define CC_MIRACLE 90756
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS)
+#define RLIB_COMPILER_ID CC_MPW
+#endif
+#endif
+#define CC_MPW 90757
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__CC_NORCROFT)
+#define RLIB_COMPILER_ID CC_NORCROFT
+#endif
+#endif
+#define CC_NORCROFT 90758
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__NWCC__)
+#define RLIB_COMPILER_ID CC_NWCC
+#endif
+#endif
+#define CC_NWCC 90759
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__OPEN64__) || defined(__OPENCC__)
+#define RLIB_COMPILER_ID CC_OPEN64
+#endif
+#endif
+#define CC_OPEN64 90760
+
+#ifndef RLIB_COMPILER_ID
+#if defined(ORA_PROC)
+#define RLIB_COMPILER_ID CC_ORACLE_PROC
+#endif
+#endif
+#define CC_ORACLE_PROC 90761
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#define RLIB_COMPILER_ID CC_SOLARIS
+#endif
+#endif
+#define CC_SOLARIS 90762
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__PACIFIC__)
+#define RLIB_COMPILER_ID CC_PACIFIC
+#endif
+#endif
+#define CC_PACIFIC 90763
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_PACC_VER)
+#define RLIB_COMPILER_ID CC_PLAM
+#endif
+#endif
+#define CC_PLAM 90764
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__POCC__)
+#define RLIB_COMPILER_ID CC_PELLES
+#endif
+#endif
+#define CC_PELLES 90765
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__PGI)
+#define RLIB_COMPILER_ID CC_PORTLAND
+#endif
+#endif
+#define CC_PORTLAND 90766
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__RENESAS__) || defined(__HITACHI__)
+#define RLIB_COMPILER_ID CC_RENESAS
+#endif
+#endif
+#define CC_RENESAS 90767
+
+#ifndef RLIB_COMPILER_ID
+#if defined(SASC) || defined(__SASC) || defined(__SASC__)
+#define RLIB_COMPILER_ID CC_SASC
+#endif
+#endif
+#define CC_SASC 90768
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_SCO_DS)
+#define RLIB_COMPILER_ID CC_SCO_OPENSERVER
+#endif
+#endif
+#define CC_SCO_OPENSERVER 90769
+
+#ifndef RLIB_COMPILER_ID
+#if defined(SDCC)
+#define RLIB_COMPILER_ID CC_SDCC
+#endif
+#endif
+#define CC_SDCC 90770
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__SNC__)
+#define RLIB_COMPILER_ID CC_SN
+#endif
+#endif
+#define CC_SN 90771
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__VOSC__)
+#define RLIB_COMPILER_ID CC_STRATUS_VOS
+#endif
+#endif
+#define CC_STRATUS_VOS 90772
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__SC__)
+#define RLIB_COMPILER_ID CC_SYMANTEC
+#endif
+#endif
+#define CC_SYMANTEC 90773
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__TenDRA__)
+#define RLIB_COMPILER_ID CC_TENDRA
+#endif
+#endif
+#define CC_TENDRA 90774
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__TI_COMPILER_VERSION__) || defined(_TMS320C6X)
+#define RLIB_COMPILER_ID CC_TEXAS
+#endif
+#endif
+#define CC_TEXAS 90775
+
+#ifndef RLIB_COMPILER_ID
+#if defined(THINKC3) || defined(THINKC4)
+#define RLIB_COMPILER_ID CC_THINK
+#endif
+#endif
+#define CC_THINK 90776
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__TINYC__)
+#define RLIB_COMPILER_ID CC_TINYC
+#endif
+#endif
+#define CC_TINYC 90777
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__TURBOC__)
+#define RLIB_COMPILER_ID CC_TURBOC
+#endif
+#endif
+#define CC_TURBOC 90778
+
+#ifndef RLIB_COMPILER_ID
+#if defined(_UCC)
+#define RLIB_COMPILER_ID CC_UCC
+#endif
+#endif
+#define CC_UCC 90779
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__USLC__)
+#define RLIB_COMPILER_ID CC_USLC
+#endif
+#endif
+#define CC_USLC 90780
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__VBCC__)
+#define RLIB_COMPILER_ID CC_VBCC
+#endif
+#endif
+#define CC_VBCC 90781
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__WATCOMC__)
+#define RLIB_COMPILER_ID CC_WATCOM
+#endif
+#endif
+#define CC_WATCOM 90782
+
+#ifndef RLIB_COMPILER_ID
+#if defined(__ZTC__)
+#define RLIB_COMPILER_ID CC_ZORTECH
+#endif
+#endif
+#define CC_ZORTECH 90783
+
+#ifndef RLIB_COMPILER_ID
+#define RLIB_COMPILER_ID CC_UNKNOWN
+#endif
+#define CC_UNKNOWN 90784
diff --git a/nemu/include/rlib/sys/fd.hpp b/nemu/include/rlib/sys/fd.hpp
new file mode 100644
index 0000000..26ea0f1
--- /dev/null
+++ b/nemu/include/rlib/sys/fd.hpp
@@ -0,0 +1,14 @@
+#ifndef RLIB_FD_HPP_
+#define RLIB_FD_HPP_
+
+#include <rlib/sys/os.hpp>
+#if RLIB_OS_ID == OS_WINDOWS
+#include <Windows.h>
+using fd_t = HANDLE;
+using sockfd_t = SOCKET;
+#else
+using fd_t = int;
+using sockfd_t = int;
+#endif
+
+#endif
diff --git a/nemu/include/rlib/sys/os.hpp b/nemu/include/rlib/sys/os.hpp
new file mode 100644
index 0000000..1843522
--- /dev/null
+++ b/nemu/include/rlib/sys/os.hpp
@@ -0,0 +1,98 @@
+#ifndef R_OS_HPP
+#define R_OS_HPP
+
+#ifndef RLIB_OS_ID
+#if defined(_Windows) || defined(__WIN32__) || defined(_WIN64) || defined(WIN32)
+#   define RLIB_OS_ID OS_WINDOWS
+#elif defined(__linux__) || defined(__linux)
+#   define RLIB_OS_ID OS_LINUX
+#elif defined(__APPLE__)
+#   include "TargetConditionals.h"
+#   if TARGET_IPHONE_SIMULATOR
+#   define RLIB_OS_ID OS_IOS
+#   elif TARGET_OS_IPHONE
+#   define RLIB_OS_ID OS_IOS
+#   elif TARGET_OS_MAC
+#   define RLIB_OS_ID OS_MACOS
+#   else
+#   define RLIB_OS_ID OS_UNKNOWN
+#   endif
+#elif defined(__OS_ANDROID__)
+#   define RLIB_OS_ID OS_ANDROID
+#elif defined(__unix__) || defined(__unix)
+#   define RLIB_OS_ID OS_UNIX
+#else
+#   define RLIB_OS_ID OS_UNKNOWN
+#endif
+#endif
+
+#define RLIB_OS_ID_MAGIC 980427
+#define OS_WINDOWS (RLIB_OS_ID_MAGIC + 1) 
+#define OS_LINUX   (RLIB_OS_ID_MAGIC + 2) 
+#define OS_MACOS   (RLIB_OS_ID_MAGIC + 3) 
+#define OS_BSD     (RLIB_OS_ID_MAGIC + 4) 
+#define OS_IOS     (RLIB_OS_ID_MAGIC + 5) 
+#define OS_ANDROID (RLIB_OS_ID_MAGIC + 6) 
+#define OS_UNIX    (RLIB_OS_ID_MAGIC + 7) 
+#define OS_UNKNOWN (RLIB_OS_ID_MAGIC + 8) 
+
+#include "compiler_detector"
+// Define RLIB_COMPILER_ID and RLIB_COMPILER_VER
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define RLIB_COMPILER_IS_MINGW 1
+#else
+#define RLIB_COMPILER_IS_MINGW 0
+#endif
+
+// shorthand for __cplusplus macro.
+#ifndef RLIB_CXX_STD
+#   if RLIB_COMPILER_ID == CC_MSVC
+#       if defined(__cplusplus)
+#       if __cplusplus == 199711L
+#           pragma message (": warning MSVC_Wrong__cplusplus: Your MSVC is possibly set __cplusplus to wrong value. Please upgrade to VS2017 15.7 Preview 3 and recompile with /Zc:__cplusplus. Or I'll assume you support C++17 and set RLIB_CXX_STD to 2017. (refer to https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/)")
+#           define RLIB_CXX_STD 2017
+#       else
+#           define RLIB_CXX_STD (__cplusplus / 100L)
+#       endif
+#       endif
+#   else
+#       if defined(__cplusplus)
+#       define RLIB_CXX_STD (__cplusplus / 100L)
+#       endif
+#   endif
+#endif
+
+#if RLIB_CXX_STD >= 2011
+namespace rlib {
+    class os_info
+    {
+    public:
+        enum class os_t {UNKNOWN = OS_UNKNOWN, WINDOWS = OS_WINDOWS, LINUX = OS_LINUX, MACOS = OS_MACOS, BSD = OS_BSD, IOS = OS_IOS, ANDROID = OS_ANDROID, UNIX = OS_UNIX};
+        enum class compiler_t {UNKNOWN = CC_UNKNOWN, GCC = CC_GCC, CLANG = CC_CLANG, MSVC = CC_MSVC, ICC = CC_ICC, BORLAND = CC_BORLAND, IARC = CC_IARC, SOLARIS = CC_SOLARIS/*, ZAPCC = CC_ZAPCC*/};
+        //C = CC_Compiler which not supports cxx1x yet is not listed here. 201708.
+        
+        static constexpr os_t os = 
+    #if defined(RLIB_OS_ID)
+    (os_t)RLIB_OS_ID;
+    #else
+    os_t::UNKNOWN;
+    #endif
+        static constexpr compiler_t compiler = 
+    #if defined(RLIB_COMPILER_ID)
+    (compiler_t)RLIB_COMPILER_ID;
+    #else
+    compiler_t::UNKNOWN;
+    #endif
+        static constexpr auto compiler_version = 
+    #if defined(RLIB_COMPILER_VER)
+    RLIB_COMPILER_VER;
+    #else
+    0;
+    #endif
+    };
+}
+
+#endif
+
+#endif
diff --git a/nemu/include/rlib/sys/rwlock.hpp b/nemu/include/rlib/sys/rwlock.hpp
new file mode 100644
index 0000000..9a5be7b
--- /dev/null
+++ b/nemu/include/rlib/sys/rwlock.hpp
@@ -0,0 +1,22 @@
+#ifndef R_SWLOCK_HPP
+#define R_SWLOCK_HPP
+
+#include <pthread.h>
+namespace rlib {    
+    [[deprecated]] class RWLock
+    {
+    public:
+        RWLock() : isFree(true) {pthread_rwlock_init(&m_lock, NULL);}
+        ~RWLock() {pthread_rwlock_destroy(&m_lock);}
+        void acquireShared() {pthread_rwlock_rdlock(&m_lock);isFree = false;}
+        void acquireExclusive() {pthread_rwlock_wrlock(&m_lock);isFree = false;}
+        void release() {pthread_rwlock_unlock(&m_lock);isFree = true;}
+    //    bool tryAcquireShared() {return pthread_rwlock_tryrdlock(&m_lock) == 0;}
+    //    bool tryAcquireExclusive() {return pthread_rwlock_trywrlock(&m_lock) == 0;}
+    private:
+        pthread_rwlock_t m_lock;
+        bool isFree;
+    };
+}
+
+#endif
diff --git a/nemu/include/rlib/sys/sio.hpp b/nemu/include/rlib/sys/sio.hpp
new file mode 100644
index 0000000..bd49b58
--- /dev/null
+++ b/nemu/include/rlib/sys/sio.hpp
@@ -0,0 +1,664 @@
+#ifndef R_SIO_HPP
+#define R_SIO_HPP
+
+#include <rlib/sys/os.hpp>
+
+#if RLIB_OS_ID == OS_WINDOWS
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#endif
+
+// Include winsock2.h before windows.h
+#include <cerrno>
+#include <cstdlib>
+#include <unistd.h>
+#include <string>
+#include <stdexcept>
+
+#include <rlib/sys/fd.hpp>
+#include <rlib/sys/os.hpp>
+#include <rlib/string.hpp>
+#include <rlib/scope_guard.hpp>
+
+
+namespace rlib {
+    // Both POSIX and Win32
+    using rlib::literals::operator "" _format;
+    static inline sockfd_t quick_accept(sockfd_t sock) {
+        auto res = accept(sock, NULL, NULL);
+        if(res == -1)
+            throw std::runtime_error("accept failed. errno = {}"_format(strerror(errno)));
+        return res;
+    }
+    static inline std::pair<std::string, uint16_t> get_peer_name(sockfd_t sock) {
+        struct sockaddr_storage addr;
+        socklen_t addrlen = sizeof(addr);
+        auto res = getpeername(sock, (struct sockaddr *)&addr, &addrlen);
+        if(res == -1)
+            throw std::runtime_error("getpeername failed. errno = {}"_format(strerror(errno)));
+        std::string ipstr;
+        uint16_t port = 0;
+        if(addr.ss_family == AF_INET) {
+            struct sockaddr_in *s = (struct sockaddr_in *)&addr;
+            char str[INET_ADDRSTRLEN];
+            auto res = inet_ntop(AF_INET, &s->sin_addr, str, INET_ADDRSTRLEN);
+            if(res == NULL)
+                throw std::runtime_error("inet_ntop failed. errno = {}"_format(strerror(errno)));
+            port = ntohs(s->sin_port);
+            ipstr = str;
+        }
+        else {
+            struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
+            char str[INET6_ADDRSTRLEN];
+            auto res = inet_ntop(AF_INET6, &s->sin6_addr, str, INET6_ADDRSTRLEN);
+            if(res == NULL)
+                throw std::runtime_error("inet_ntop failed. errno = {}"_format(strerror(errno)));
+            port = ntohs(s->sin6_port);
+            ipstr = std::string() + '[' + str + ']';
+        }
+        return {ipstr, port};
+        
+
+    }
+
+#if RLIB_OS_ID != OS_WINDOWS
+    namespace impl {
+        inline void MakeNonBlocking(fd_t fd) {
+            int flags, s;
+
+            flags = fcntl (fd, F_GETFL, 0);
+            if (flags == -1) {
+                perror ("fcntl");
+                exit(-1);
+            }
+
+            flags |= O_NONBLOCK;
+            s = fcntl (fd, F_SETFL, flags);
+            if (s == -1) {
+                perror ("fcntl");
+                exit(-1);
+            }
+        }
+    }
+#endif
+
+#if RLIB_OS_ID == OS_WINDOWS
+    template <bool doNotWSAStartup = false>
+    static inline sockfd_t quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) {
+        WSADATA wsaData;
+        sockfd_t listenfd = INVALID_SOCKET;
+        if(!doNotWSAStartup) {
+            int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+            if (iResult != 0) throw std::runtime_error("WSAStartup failed with error: {}\n"_format(iResult));
+        }
+    
+        addrinfo *psaddr;
+        addrinfo hints { 0 };
+        hints.ai_family = AF_UNSPEC;
+        if(use_udp) {
+            hints.ai_socktype = SOCK_DGRAM;
+            hints.ai_protocol = IPPROTO_UDP;
+        }
+        else {
+            hints.ai_socktype = SOCK_STREAM;
+            hints.ai_protocol = IPPROTO_TCP;
+        }
+        hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
+        auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr);
+        if(_ != 0) {
+            WSACleanup();
+            throw std::runtime_error("Failed to getaddrinfo. returnval={}, check `man getaddrinfo`'s return value."_format(_));
+        }
+    
+        bool success = false;
+        for (addrinfo *rp = psaddr; rp != NULL; rp = rp->ai_next) {
+            listenfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+            if (listenfd == INVALID_SOCKET)
+                continue;
+            int reuse = 1;
+            if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(int)) < 0) throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+            if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) != SOCKET_ERROR) {
+                success = true;
+                break; /* Success */
+            }
+            closesocket(listenfd);
+        }
+        if(!success) throw std::runtime_error("Failed to bind to any of these addr.");
+    
+        if(!use_udp) {
+            // UDP don't need to listen.
+            if(SOCKET_ERROR == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno)));
+        }
+    
+        freeaddrinfo(psaddr);
+        return listenfd;
+    }
+
+    template <bool doNotWSAStartup = false>
+    static inline sockfd_t quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) {
+        WSADATA wsaData;
+        sockfd_t sockfd = INVALID_SOCKET;
+        if(!doNotWSAStartup) {
+            int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+            if (iResult != 0) throw std::runtime_error("WSAStartup failed with error: {}\n"_format(iResult));
+        }
+    
+        addrinfo *paddr;
+        addrinfo hints { 0 };
+    
+        hints.ai_family = AF_UNSPEC;
+        if(use_udp) {
+            hints.ai_socktype = SOCK_DGRAM;
+            hints.ai_protocol = IPPROTO_UDP;
+        }
+        else {
+            hints.ai_socktype = SOCK_STREAM;
+            hints.ai_protocol = IPPROTO_TCP;
+        }
+
+        auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr);
+        if(_ != 0) {
+            WSACleanup();
+            throw std::runtime_error("getaddrinfo failed. Check network connection to {}:{}; returnval={}, check `man getaddrinfo`'s return value."_format(addr.c_str(), port, _));
+        }
+        rlib_defer([p=paddr]{WSACleanup();freeaddrinfo(p);});
+    
+        bool success = false;
+        for (addrinfo *rp = paddr; rp != NULL; rp = rp->ai_next) {
+            sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+            if (sockfd == INVALID_SOCKET)
+                continue;
+            int reuse = 1;
+            if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(int)) < 0) throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+            if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != SOCKET_ERROR) {
+                success = true;
+                break; /* Success */
+            }
+            closesocket(sockfd);
+        }   
+        if(!success) throw std::runtime_error("Failed to connect to any of these addr.");
+    
+        freeaddrinfo(paddr);
+        return sockfd;
+    }
+
+#else
+    // POSIX version
+    static inline fd_t quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) {
+        addrinfo *psaddr;
+        addrinfo hints{0};
+        fd_t listenfd;
+
+        hints.ai_family = AF_UNSPEC;
+        if(use_udp) {
+            hints.ai_socktype = SOCK_DGRAM;
+            hints.ai_protocol = IPPROTO_UDP;
+        }
+        else {
+            hints.ai_socktype = SOCK_STREAM;
+            hints.ai_protocol = IPPROTO_TCP;
+        }
+        hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
+        auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr);
+        if (_ != 0) throw std::runtime_error("Failed to getaddrinfo. returnval={}, check `man getaddrinfo`'s return value."_format(_));
+
+        bool success = false;
+        for (addrinfo *rp = psaddr; rp != nullptr; rp = rp->ai_next) {
+            listenfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+            if (listenfd == -1)
+                continue;
+            int reuse = 1;
+            if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(int)) < 0)
+                throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+            if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (const char *) &reuse, sizeof(int)) < 0)
+                throw std::runtime_error("setsockopt(SO_REUSEPORT) failed");
+            if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                success = true;
+                break;
+            }
+            close(listenfd);
+        }
+        if (!success) throw std::runtime_error("Failed to bind {}:{}."_format(addr, port));
+
+        if(!use_udp) {
+            // UDP don't need to listen.
+            if (-1 == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno)));
+        }
+
+        rlib_defer([psaddr] { freeaddrinfo(psaddr); });
+        return listenfd;
+    }
+
+    static inline fd_t quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) {
+        addrinfo *paddr;
+        addrinfo hints{0};
+        fd_t sockfd;
+
+        hints.ai_family = AF_UNSPEC;
+        if(use_udp) {
+            hints.ai_socktype = SOCK_DGRAM;
+            hints.ai_protocol = IPPROTO_UDP;
+        }
+        else {
+            hints.ai_socktype = SOCK_STREAM;
+            hints.ai_protocol = IPPROTO_TCP;
+        }
+ 
+        auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr);
+        if (_ != 0)
+            throw std::runtime_error("getaddrinfo failed. Check network connection to {}:{}; returnval={}, check `man getaddrinfo`'s return value."_format(
+                    addr.c_str(), port, _));
+        rlib_defer([paddr] { freeaddrinfo(paddr); });
+
+        bool success = false;
+        for (addrinfo *rp = paddr; rp != NULL; rp = rp->ai_next) {
+            sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+            if (sockfd == -1)
+                continue;
+            int reuse = 1;
+            if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(int)) < 0)
+                throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+            if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char *) &reuse, sizeof(int)) < 0)
+                throw std::runtime_error("setsockopt(SO_REUSEPORT) failed");
+            if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                success = true;
+                break; /* Success */
+            }
+            close(sockfd);
+        }
+        if (!success) throw std::runtime_error("Failed to connect to any of these addr.");
+
+        return sockfd;
+    }
+#endif
+
+#if RLIB_OS_ID != OS_WINDOWS
+    // POSIX-only fdIO
+    class fdIO
+    {
+    public:
+        static ssize_t readn(fd_t fd, void *vptr, size_t n) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t  nleft;
+            ssize_t nread;
+            char   *ptr;
+        
+            ptr = (char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nread = read(fd, ptr, nleft)) < 0) {
+                    if (errno == EINTR)
+                        nread = 0;      /* and call read() again */
+                    else
+                        return (-1);
+                } else if (nread == 0)
+                    return (-1);              /* EOF */
+            
+                nleft -= nread;
+                ptr += nread;
+            }
+            return (n);         /* return success */
+        }
+        static ssize_t writen(fd_t fd, const void *vptr, size_t n) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t nleft;
+            ssize_t nwritten;
+            const char *ptr;
+        
+            ptr = (const char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
+                    if (nwritten < 0 && errno == EINTR)
+                        nwritten = 0;   /* and call write() again */
+                    else
+                        return (-1);    /* error */
+                 }
+             
+                 nleft -= nwritten;
+                 ptr += nwritten;
+            }
+            return (n);
+        }
+        static ssize_t readall(fd_t fd, void **pvptr, size_t initSize) noexcept //Return -1 on error, read bytes on success. pvptr must be a malloc/calloced buffer, I'll malloc one if *pvptr is NULL.
+        {
+            size_t current = initSize ? initSize : 1024;
+            void *vptr = *pvptr;
+            if(vptr == NULL)
+                vptr = malloc(current);
+            void *currvptr = vptr;
+        
+            {
+                ssize_t ret = read(fd, currvptr, current / 2);
+                if(ret == -1) return -1;
+                if(ret < current / 2)
+                {
+                    *pvptr = vptr;
+                    return ret;
+                }
+                currvptr = (char *)vptr + current / 2;
+            }
+        
+            while(true)
+            {
+                ssize_t ret = read(fd, currvptr, current / 2);
+                if(ret == -1) return -1;
+                if(ret < current)
+                {
+                    *pvptr = vptr;
+                    return ret + current / 2;
+                }
+            
+                current *= 2;
+                void *vptrBackup = vptr;
+                if((vptr = realloc(vptr, current)) == NULL) {
+                    free(vptrBackup);
+                    errno = EMSGSIZE;
+                    return -1;
+                }
+                currvptr = (char *)vptr + current / 2;
+            }
+        }
+        static void readn_ex(fd_t fd, void *vptr, size_t n) //never return error.
+        {
+            auto ret = readn(fd, vptr, n);
+            if(ret == -1) throw std::runtime_error("readn failed. errno = {}"_format(strerror(errno)));
+        }
+        static void writen_ex(fd_t fd, const void *vptr, size_t n)
+        {
+            auto ret = writen(fd, vptr, n);
+            if(ret == -1) throw std::runtime_error("writen failed. errno = {}"_format(strerror(errno)));
+        }
+        static ssize_t readall_ex(fd_t fd, void **pvptr, size_t initSize) //never return -1
+        {
+            auto ret = readall(fd, pvptr, initSize);
+            if(ret == -1) throw std::runtime_error("readall failed. errno = {}"_format(strerror(errno)));
+            return ret;
+        }
+        static std::string quick_readn(fd_t fd, size_t n) {
+            std::string res(n, '0');
+            readn_ex(fd, (void *)res.data(), n);
+            return res;
+        }
+        static std::string quick_readall(fd_t fd) {
+            void *ptr;
+            auto size = readall_ex(fd, &ptr, 0);
+            return std::string((char *)ptr, size);
+        }
+        static void quick_write(fd_t fd, const std::string &data) {
+            writen_ex(fd, data.data(), data.size());
+        }
+    };
+#endif
+
+    // Win32 sockIO
+    class sockIO 
+    {
+#if RLIB_OS_ID == OS_WINDOWS
+    private:
+        static int WSASafeGetLastError()
+        {
+            int i;
+            WSASetLastError(i = WSAGetLastError());
+            return i;
+        }
+    public:
+        static ssize_t recvn(sockfd_t fd, void *vptr, size_t n, int flags) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t  nleft;
+            ssize_t nread;
+            char   *ptr;
+        
+            ptr = (char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nread = recv(fd, ptr, nleft, flags)) == SOCKET_ERROR) {
+                    if (WSASafeGetLastError() == WSAEINTR)
+                        nread = 0;      /* and call read() again */
+                    else
+                        return (-1);
+                } else if (nread == 0)
+                    return (-1);              /* EOF */
+            
+                nleft -= nread;
+                ptr += nread;
+            }
+            return (n);         /* return >= 0 */
+        }
+        static ssize_t sendn(sockfd_t fd, const void *vptr, size_t n, int flags) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t nleft;
+            ssize_t nwritten;
+            const char *ptr;
+        
+            ptr = (const char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nwritten = send(fd, ptr, nleft, flags)) <= 0) {
+                    if (nwritten == SOCKET_ERROR && WSASafeGetLastError() == WSAEINTR)
+                        nwritten = 0;   /* and call write() again */
+                    else
+                        return (-1);    /* error */
+                 }
+             
+                 nleft -= nwritten;
+                 ptr += nwritten;
+            }
+            return (n);
+        }
+        static ssize_t recvall(sockfd_t fd, void **pvptr, size_t initSize, int flags) noexcept //Return -1 on error, read bytes on success. pvptr must be a malloc/calloced buffer, I'll malloc one if *pvptr is NULL.
+        {
+            size_t current = initSize ? initSize : 1024;
+            void *vptr = *pvptr;
+            if(vptr == NULL)
+                vptr = malloc(current);
+            void *currvptr = vptr;
+        
+            {
+            _retry_1:
+                ssize_t ret = recv(fd, (char *)currvptr, current / 2, flags); 
+                if(ret == SOCKET_ERROR) {
+                    if(WSASafeGetLastError() == WSAEINTR)
+                        goto _retry_1;
+                    return SOCKET_ERROR;
+                }
+                if(ret < current / 2)
+                {
+                    *pvptr = vptr;
+                    return ret;
+                }
+                currvptr = (char *)vptr + current / 2;
+            }   
+        
+            while(true)
+            {
+                ssize_t ret = recv(fd, (char *)currvptr, current / 2, flags); 
+                if(ret == SOCKET_ERROR) {
+                    if(WSASafeGetLastError() == WSAEINTR)
+                        continue; //retry
+                    return SOCKET_ERROR;
+                }
+                if(ret < current)
+                {
+                    *pvptr = vptr;
+                    return ret + current / 2;
+                }
+        
+                current *= 2;
+                void *vptrBackup = vptr;
+                if((vptr = realloc(vptr, current)) == NULL) {
+                    free(vptrBackup);
+                    WSASetLastError(WSAEMSGSIZE);
+                    return SOCKET_ERROR;
+                }   
+                currvptr = (char *)vptr + current / 2;
+            }
+        }
+#else 
+    // POSIX sockIO
+    public:
+        static ssize_t recvn(sockfd_t fd, void *vptr, size_t n, int flags) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t  nleft;
+            ssize_t nread;
+            char   *ptr;
+        
+            ptr = (char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nread = recv(fd, ptr, nleft, flags)) < 0) {
+                    if (errno == EINTR)
+                        nread = 0;      /* and call read() again */
+                    else
+                        return (-1);
+                } else if (nread == 0)
+                    return -1;              /* EOF */
+            
+                nleft -= nread;
+                ptr += nread;
+            }
+            return (n);         /* return success */
+        }
+        static ssize_t sendn(sockfd_t fd, const void *vptr, size_t n, int flags) noexcept //Return -1 on error, read bytes on success, blocks until nbytes done.
+        {
+            size_t nleft;
+            ssize_t nwritten;
+            const char *ptr;
+        
+            ptr = (const char *)vptr;
+            nleft = n;
+            while (nleft > 0) {
+                if ( (nwritten = send(fd, ptr, nleft, flags)) <= 0) {
+                    if (nwritten < 0 && errno == EINTR)
+                        nwritten = 0;   /* and call write() again */
+                    else
+                        return (-1);    /* error */
+                 }
+             
+                 nleft -= nwritten;
+                 ptr += nwritten;
+            }
+            return (n);
+        }
+        static ssize_t recvall(sockfd_t fd, void **pvptr, size_t initSize, int flags) noexcept //Return -1 on error, read bytes on success. pvptr must be a malloc/calloced buffer, I'll malloc one if *pvptr is NULL.
+        {
+            size_t current = initSize ? initSize : 1024;
+            void *vptr = *pvptr;
+            if(vptr == NULL)
+                vptr = malloc(current);
+            void *currvptr = vptr;
+        
+            {
+                ssize_t ret = recv(fd, currvptr, current / 2, flags);
+                if(ret == -1) return -1;
+                if(ret < current / 2)
+                {
+                    *pvptr = vptr;
+                    return ret;
+                }
+                currvptr = (char *)vptr + current / 2;
+            }
+        
+            while(true)
+            {
+                ssize_t ret = recv(fd, currvptr, current / 2, flags);
+                if(ret == -1) return -1;
+                if(ret < current)
+                {
+                    *pvptr = vptr;
+                    return ret + current / 2;
+                }
+            
+                current *= 2;
+                void *vptrBackup = vptr;
+                if((vptr = realloc(vptr, current)) == NULL) {
+                    free(vptrBackup);
+                    errno = EMSGSIZE;
+                    return -1;
+                }
+                currvptr = (char *)vptr + current / 2;
+            }
+        }
+#endif
+
+#ifndef MSG_NOSIGNAL
+    private:
+        static constexpr int MSG_NOSIGNAL = 0;
+#endif
+        // both POSIX and Win32
+    public:
+        static void recvn_ex(sockfd_t fd, void *vptr, size_t n, int flags) //return read bytes.
+        {
+            auto ret = recvn(fd, vptr, n, flags);
+            if(ret == -1) throw std::runtime_error("recvn failed. {}"_format(strerror(errno)));
+        }
+        static void sendn_ex(sockfd_t fd, const void *vptr, size_t n, int flags)
+        {
+            auto ret = sendn(fd, vptr, n, flags);
+            if(ret == -1) throw std::runtime_error("sendn failed. {}"_format(strerror(errno)));
+        }
+        static ssize_t recvall_ex(sockfd_t fd, void **pvptr, size_t initSize, int flags) //never return -1
+        {
+            auto ret = recvall(fd, pvptr, initSize, flags);
+            if(ret == -1) throw std::runtime_error("recvall failed. {}"_format(strerror(errno)));
+            return ret;
+        }
+
+        static std::string quick_recvn(sockfd_t fd, size_t n) {
+            std::string res(n, '0');
+            recvn_ex(fd, (void *)res.data(), n, MSG_NOSIGNAL);
+            return res;
+        }
+        static std::string quick_recvall(sockfd_t fd) {
+            void *ptr = NULL;
+            auto size = recvall_ex(fd, &ptr, 0, MSG_NOSIGNAL);
+            auto result = std::string((char *)ptr, size);
+            free(ptr);
+            return result;
+        }
+        static void quick_send(sockfd_t fd, const std::string &data) {
+            sendn_ex(fd, data.data(), data.size(), MSG_NOSIGNAL);
+        }
+
+        // practical message with head
+    private:
+#pragma pack(push, 1)
+        struct packed_msg_head {
+            uint32_t magic = 0x19980427;
+            uint64_t len;
+        };
+#pragma pack(pop)
+        static_assert(sizeof(packed_msg_head) == sizeof(uint32_t) + sizeof(uint64_t), "Compiler doesn't compile the struct `packed_msg_head` as packed.");
+    public:
+        static std::string recv_msg(sockfd_t fd) {
+            packed_msg_head head;
+            recvn_ex(fd, &head, sizeof(head), MSG_NOSIGNAL);
+            if(head.magic != 0x19980427)
+                throw std::runtime_error("Invalid magic received.");
+            if(head.len > 1024ull*1024*1024*2)
+                throw std::runtime_error("Message len is greater than 2GiB. Refuse to alloc space.");
+            std::string dat(head.len, '\0');
+            recvn_ex(fd, (void *)dat.data(), head.len, MSG_NOSIGNAL);
+            return dat;
+        }
+        static void send_msg(sockfd_t fd, const std::string &dat) {
+            packed_msg_head head;
+            head.len = dat.size();
+            sendn_ex(fd, &head, sizeof(head), MSG_NOSIGNAL);
+            sendn_ex(fd, dat.data(), head.len, MSG_NOSIGNAL);
+        }
+
+    };
+
+
+} // namespace rlib
+
+
+#endif
diff --git a/nemu/include/rlib/sys/time.hpp b/nemu/include/rlib/sys/time.hpp
new file mode 100644
index 0000000..81538b3
--- /dev/null
+++ b/nemu/include/rlib/sys/time.hpp
@@ -0,0 +1,18 @@
+#ifndef RLIB_TIME_HPP_
+#define RLIB_TIME_HPP_
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+namespace rlib {
+    static inline std::string get_current_time_str() noexcept {
+        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+        std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
+        static char mbstr[128];
+        if (std::strftime(mbstr, sizeof(mbstr), "%c", std::localtime(&now_c))) {
+            return mbstr;
+        }
+        throw std::overflow_error("on get_current_time: mbstr buffer is too small.");
+    }
+}
+#endif
diff --git a/nemu/include/rlib/sys/unix_handy.hpp b/nemu/include/rlib/sys/unix_handy.hpp
new file mode 100644
index 0000000..ffc63bc
--- /dev/null
+++ b/nemu/include/rlib/sys/unix_handy.hpp
@@ -0,0 +1,170 @@
+#ifndef RLIB_UNIX_HANDY_HPP_
+#define RLIB_UNIX_HANDY_HPP_
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <rlib/scope_guard.hpp>
+#include <rlib/string.hpp>
+
+#include <rlib/sys/os.hpp>
+#if RLIB_OS_ID == OS_WINDOWS
+#error rlib/sys/unix_handy.hpp is not for Windows.
+#endif
+
+// Deprecated. Use sys/sio.hpp
+#if 1+1 == 4
+namespace rlib {
+    namespace impl {
+        using rlib::literals::operator""_format;
+        static inline fd unix_quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) {
+            addrinfo *psaddr;
+            addrinfo hints{0};
+            fd listenfd;
+
+            hints.ai_family = AF_UNSPEC;
+            if(use_udp) {
+                hints.ai_socktype = SOCK_DGRAM;
+                hints.ai_protocol = IPPROTO_UDP;
+            }
+            else {
+                hints.ai_socktype = SOCK_STREAM;
+                hints.ai_protocol = IPPROTO_TCP;
+            }
+            hints.ai_flags = AI_PASSIVE;    /* For listen */
+            auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr);
+            if (_ != 0) throw std::runtime_error("Failed to getaddrinfo. returnval={}, check `man getaddrinfo`'s return value."_format(_));
+
+            bool success = false;
+            for (addrinfo *rp = psaddr; rp != nullptr; rp = rp->ai_next) {
+                listenfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+                if (listenfd == -1)
+                    continue;
+                int reuse = 1;
+                if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(int)) < 0)
+                    throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+                if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (const char *) &reuse, sizeof(int)) < 0)
+                    throw std::runtime_error("setsockopt(SO_REUSEPORT) failed");
+                if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                    success = true;
+                    break;
+                }
+                close(listenfd);
+            }
+            if (!success) throw std::runtime_error("Failed to bind {}:{}."_format(addr, port));
+
+            if (-1 == ::listen(listenfd, 16)) throw std::runtime_error("listen failed.");
+
+            rlib_defer([psaddr] { freeaddrinfo(psaddr); });
+            return listenfd;
+        }
+
+        static inline fd unix_quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) {
+            addrinfo *paddr;
+            addrinfo hints{0};
+            fd sockfd;
+
+            hints.ai_family = AF_UNSPEC;
+            if(use_udp) {
+                hints.ai_socktype = SOCK_DGRAM;
+                hints.ai_protocol = IPPROTO_UDP;
+            }
+            else {
+                hints.ai_socktype = SOCK_STREAM;
+                hints.ai_protocol = IPPROTO_TCP;
+            }
+            auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr);
+            if (_ != 0)
+                throw std::runtime_error("getaddrinfo failed. Check network connection to {}:{}; returnval={}, check `man getaddrinfo`'s return value."_format(
+                        addr.c_str(), port, _));
+            rlib_defer([paddr] { freeaddrinfo(paddr); });
+
+            bool success = false;
+            for (addrinfo *rp = paddr; rp != NULL; rp = rp->ai_next) {
+                sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+                if (sockfd == -1)
+                    continue;
+                int reuse = 1;
+                if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(int)) < 0)
+                    throw std::runtime_error("setsockopt(SO_REUSEADDR) failed");
+                if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char *) &reuse, sizeof(int)) < 0)
+                    throw std::runtime_error("setsockopt(SO_REUSEPORT) failed");
+                if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0) {
+                    success = true;
+                    break; /* Success */
+                }
+                close(sockfd);
+            }
+            if (!success) throw std::runtime_error("Failed to connect to any of these addr.");
+
+            return sockfd;
+        }
+    }
+    using impl::unix_quick_connect;
+    using impl::unix_quick_listen;
+}
+#endif
+
+
+// Unfinished. I'm not sure if I must implement it.
+#if 1+1 == 3
+#include <fstream>
+#include <iostream>
+#if RLIB_COMPILER_ID == CC_GCC 
+#include <ext/stdio_filebuf.h>
+namespace rlib {
+    inline std::istream & fd_to_istream(fd handle) {
+        if(handle == STDIN_FILENO) return std::cin;
+        __gnu_cxx::stdio_filebuf<char> filebuf(handle, std::ios::in);
+        return std::istream(&filebuf);
+    }
+    inline std::ostream & fd_to_ostream(fd handle) {
+        if(handle == STDOUT_FILENO) return std::cout;
+        if(handle == STDERR_FILENO) return std::cerr;
+        __gnu_cxx::stdio_filebuf<char> filebuf(handle, std::ios::out);
+        return std::ostream(&filebuf);
+    }
+    inline std::iostream & fd_to_iostream(fd handle) {
+        __gnu_cxx::stdio_filebuf<char> filebuf(handle, std::ios::in | std::ios::out);
+        return std::iostream(&filebuf);
+    }
+} // rlib
+#elif RLIB_COMPILER_ID == CC_MSVC
+namespace rlib {
+    inline std::istream & fd_to_istream(fd handle) {
+        if(handle == STDIN_FILENO) return std::cin;
+        ifstream fs(::_fdopen(handle, "r"));
+        return fs;
+    }
+    inline std::ostream & fd_to_ostream(fd handle) {
+        if(handle == STDOUT_FILENO) return std::cout;
+        if(handle == STDERR_FILENO) return std::cerr;
+        ofstream fs(::_fdopen(handle, "w"));
+        return fs;
+    }
+    inline std::iostream & fd_to_iostream(fd handle) {
+        fstream fs(::_fdopen(handle, "rw"));
+        return fs;
+    }
+} // rlib
+#else
+namespace rlib {
+    constexpr inline std::istream & fd_to_istream(fd handle) {
+        if(handle == STDIN_FILENO) return std::cin;
+        throw std::invalid_argument("fd != 0 to istream is not implemented except gcc/msvc.");
+    }
+    constexpr inline std::ostream & fd_to_ostream(fd handle) {
+        if(handle == STDOUT_FILENO) return std::cout;
+        if(handle == STDERR_FILENO) return std::cerr;
+        throw std::invalid_argument("fd != 1/2 to ostream is not implemented except gcc/msvc.");
+    }
+    constexpr inline std::iostream & fd_to_iostream(fd handle) {
+        throw std::invalid_argument("fd to iostream is not implemented except gcc/msvc.");
+    }
+
+} // rlib
+#endif // if compiler
+#endif // if 1+1==3
+
+#endif // header guarder
diff --git a/nemu/include/rlib/terminal.hpp b/nemu/include/rlib/terminal.hpp
new file mode 100644
index 0000000..472c122
--- /dev/null
+++ b/nemu/include/rlib/terminal.hpp
@@ -0,0 +1,100 @@
+/*
+ *
+ * terminal.hpp: unix terminal font/color wrapper for modern c++
+ * by Recolic Keghart <root@recolic.net>
+ * MIT License
+ *
+ * */
+
+#ifndef R_STD_COLOR_HPP
+#define R_STD_COLOR_HPP
+
+#include <rlib/require/cxx11>
+#include <rlib/sys/os.hpp>
+
+#include <iostream>
+#include <string>
+#include <stdexcept>
+#include <exception>
+using std::string;
+using std::basic_ostream;
+
+namespace rlib::terminal {
+    enum class color_t {color_unset = 10, black = 0, red, green, brown, blue, magenta, cyan, lightgray};
+    enum class font_t {font_unset = 0, bold = 1, underline = 4, dark = 2, background = 7, striked = 9}; //Edit line53 if (int)font_t may >= 10 !!
+    class clear_t {} clear;
+
+    class fontInfo
+    {
+    public:
+        fontInfo(color_t text_color) : textColor(text_color) {}
+        fontInfo(font_t font_type) : fontType(font_type) {}
+        fontInfo(color_t text_color, font_t font_type) : textColor(text_color), fontType(font_type) {}
+        fontInfo(const clear_t &) : clear(true) {}
+        fontInfo() = default;
+        string toString() const
+        {
+            if(rlib::os_info::os == rlib::os_info::os_t::WINDOWS)
+                return std::move(std::string());
+            else
+                return std::move(clear ? std::string("\033[0m") : (color_to_string() + font_to_string()));
+        }
+    private:
+        color_t textColor = color_t::color_unset;
+        font_t fontType = font_t::font_unset;
+        bool clear = false;
+    private:
+        constexpr static int color_to_int(const color_t &_ct)
+        {
+            return static_cast<int>(_ct);
+        }
+        constexpr static int font_to_int(const font_t &_ft)
+        {
+            return static_cast<int>(_ft);
+        }
+        constexpr static char color_to_char(const color_t &_ct)
+        {
+            return _ct == color_t::color_unset ? '\0' : '0' + color_to_int(_ct); //Return '\0' if unset.
+        }
+        constexpr static char font_to_char(const font_t &_ft)
+        {
+            return _ft == font_t::font_unset ? '\0' :'0' + font_to_int(_ft);
+        }
+        string color_to_string() const
+        {
+            if(textColor == color_t::color_unset)
+                return std::move(std::string());
+            char toret[] = "\033[3?m";
+            toret[3] = color_to_char(textColor);
+            return std::move(std::string(toret));
+        }
+        string font_to_string() const
+        {
+            if(fontType == font_t::font_unset)
+                return std::move(std::string());
+            char toret[] = "\033[?m";
+            toret[2] = font_to_char(fontType);
+            return std::move(std::string(toret)); 
+        }
+    };
+    
+    struct _rosi_font {_rosi_font(const fontInfo &_ref_fi) : _ref_fi(_ref_fi) {} const fontInfo &_ref_fi;};
+    inline _rosi_font setfont(const fontInfo &__fi) {return _rosi_font(__fi);}
+
+    template<typename _CharT, typename _Traits>
+        inline basic_ostream<_CharT, _Traits>& 
+        operator<<(basic_ostream<_CharT, _Traits>& __os, const fontInfo &__f)
+        {
+            __os << __f.toString();
+            return __os;
+        }
+
+    template<typename _CharT, typename _Traits>
+        inline basic_ostream<_CharT, _Traits>& 
+        operator<<(basic_ostream<_CharT, _Traits>& __os, _rosi_font __rosi_f)
+        {
+            const fontInfo &__f = __rosi_f._ref_fi;
+            return operator<<<_CharT, _Traits>(__os, __f);
+        }
+}
+#endif
diff --git a/nemu/include/rlib/traits.hpp b/nemu/include/rlib/traits.hpp
new file mode 100644
index 0000000..f15fba3
--- /dev/null
+++ b/nemu/include/rlib/traits.hpp
@@ -0,0 +1,38 @@
+#ifndef RLIB_TRAITS_HPP
+#define RLIB_TRAITS_HPP
+
+#include <type_traits>
+
+namespace rlib{
+    namespace impl {
+        template<typename T>
+        struct is_callable_helper {
+        private:
+            typedef char(&yes)[1];
+            typedef char(&no)[2];
+    
+            struct Fallback { void operator()(); };
+            struct Derived : T, Fallback { };
+    
+            template<typename U, U> struct Check;
+    
+            template<typename>
+            static yes test(...);
+    
+            template<typename C>
+            static no test(Check<void (Fallback::*)(), &C::operator()>*);
+    
+            static constexpr bool value = sizeof(test<Derived>(0)) == sizeof(yes);
+        public:
+            static constexpr bool real_value = std::conditional<std::is_class<T>::value, impl::is_callable_helper<T>, std::is_function<T>>::type::value;
+        };
+    } //impl
+} //rlib
+
+namespace rlib {
+    template<typename T>
+    struct is_callable : public std::bool_constant<impl::is_callable_helper<T>::real_value> {
+    };
+}
+
+#endif
diff --git a/nemu/runall.sh b/nemu/runall.sh
old mode 100644
new mode 100755
index a8d5b28..60c4a90
--- a/nemu/runall.sh
+++ b/nemu/runall.sh
@@ -1,26 +1,33 @@
 #!/bin/bash
 
 nemu=build/nemu
+[[ $show_log = 1 ]] && g_logfile=/tmp/nemu.test.log || g_logfile=/dev/null
 
 echo "compiling NEMU..."
-if make &> /dev/null; then
+if make &> "$g_logfile"; then
   echo "NEMU compile OK"
 else
-  echo "testcases compile error... exit..."
-  exit
+  echo "NEMU compile error... exit..."
+  cat "$g_logfile"
+  exit 1
 fi
 
 echo "compiling testcases..."
-if make -C $AM_HOME/tests/cputest ARCH=x86-nemu &> /dev/null; then
+if make -C $AM_HOME/tests/cputest ARCH=x86-nemu &> "$g_logfile"; then
   echo "testcases compile OK"
+  cat "$g_logfile"
 else
   echo "testcases compile error... exit..."
-  exit
+  cat "$g_logfile"
+  exit 1
 fi
 
+[[ $show_log = 1 ]] && rm $g_logfile
 files=`ls $AM_HOME/tests/cputest/build/*-x86-nemu.bin`
 ori_log="build/nemu-log.txt"
 
+has_fail=0
+
 for file in $files; do
   base=`basename $file | sed -e 's/-x86-nemu.bin//'`
   printf "[%14s] " $base
@@ -29,12 +36,17 @@ for file in $files; do
 
   if (grep 'nemu: HIT GOOD TRAP' $logfile > /dev/null) then
     echo -e "\033[1;32mPASS!\033[0m"
-    rm $logfile
   else
     echo -e "\033[1;31mFAIL!\033[0m see $logfile for more information"
+    has_fail=1
     if (test -e $ori_log) then
       echo -e "\n\n===== the original log.txt =====\n" >> $logfile
       cat $ori_log >> $logfile
     fi
+    grep 'HIT GOOD TRAP' $logfile > /dev/null || head -n 512 $logfile >> $g_logfile
   fi
+  rm -f $logfile
 done
+
+[[ $has_fail = 1 ]] && cat $g_logfile
+exit $has_fail
-- 
GitLab