diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d6bc5d0dd29a3a643caa684bfe6b7dac805bd96..6ce6f1f52c0b1498d93361351ae9605b1e8b5fa7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 2.6)
 
-project(tarantool)
+project(tarantool C CXX)
 
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_INCLUDE_PATH})
@@ -13,7 +13,6 @@ include(CheckCSourceRuns)
 include(CheckCXXSourceRuns)
 include(TestBigEndian)
 include(CheckFunctionExists)
-include(CheckBuiltInFunctionExists)
 
 find_program(ECHO echo)
 find_program(XSLTPROC xsltproc)
@@ -260,33 +259,6 @@ add_custom_target(build_bundled_libs)
 #
 include(luajit)
 
-#
-# LibOBJC
-#
-set (ENABLE_BUNDLED_LIBOBJC_DEFAULT ON)
-if (TARGET_OS_DARWIN)
-    set (ENABLE_BUNDLED_LIBOBJC_DEFAULT OFF)
-endif()
-option(ENABLE_BUNDLED_LIBOBJC "Enable building of the bundled libobjc" ${ENABLE_BUNDLED_LIBOBJC_DEFAULT})
-
-if (ENABLE_BUNDLED_LIBOBJC)
-    include(BuildLibOBJC)
-    libobjc_build()
-    add_dependencies(build_bundled_libs objc)
-    set(HAVE_LIBOBJC_BUNDLED ON)
-else()
-    if (CMAKE_COMPILER_IS_GNUCC)
-        # Use compiler's objc library
-        add_compile_flags("OBJC;OBJCXX" "-objc")
-        set(LIBOBJC_LIBRARIES objc)
-        message(STATUS "Use gcc Objective-C runtime")
-    else()
-        set(LIBOBJC_FIND_REQUIRED ON)
-        find_package(LibOBJC)
-    endif()
-endif()
-
-
 #
 # LibEV
 #
@@ -413,8 +385,6 @@ message (STATUS "C_COMPILER: ${TARANTOOL_C_COMPILER}")
 message (STATUS "CXX_COMPILER: ${TARANTOOL_CXX_COMPILER}")
 message (STATUS "C_FLAGS:${TARANTOOL_C_FLAGS}")
 message (STATUS "CXX_FLAGS:${TARANTOOL_CXX_FLAGS}")
-message (STATUS "OBJC_FLAGS:${TARANTOOL_OBJC_FLAGS}")
-message (STATUS "OBJCXX_FLAGS:${TARANTOOL_OBJCXX_FLAGS}")
 message (STATUS "PREFIX: ${CMAKE_INSTALL_PREFIX}")
 message (STATUS "MODULES: ${TARANTOOL_MODULES}")
 message (STATUS "ENABLE_STATIC: ${ENABLE_STATIC}")
diff --git a/cfg/warning.c b/cfg/warning.c
index c3887e92ed848d8942b8914a77a70d9fab3bb063..8fbc242d70874ba91ca32bcad5808c957576001d 100644
--- a/cfg/warning.c
+++ b/cfg/warning.c
@@ -12,7 +12,7 @@ struct tbuf *cfg_out = NULL;
  */
 
 void
-out_warning(ConfettyError v, char *format, ...)
+out_warning(ConfettyError v, const char *format, ...)
 {
 	va_list ap;
 
diff --git a/cfg/warning.h b/cfg/warning.h
index 58792abe3ae53dc9bbfc967f4b0d7a6eccd162c8..646688b498fb6635a2e34616cfd463b6157531e9 100644
--- a/cfg/warning.h
+++ b/cfg/warning.h
@@ -5,6 +5,6 @@
 
 extern struct tbuf *cfg_out;
 
-void out_warning(ConfettyError r, char *format, ...);
+void out_warning(ConfettyError r, const char *format, ...);
 
 #endif
diff --git a/client/tarantool_checksum/tc_space.c b/client/tarantool_checksum/tc_space.c
index f7697f69dceff5c2f9ad88723f341a39fb59fbd5..4d76a771ffe4829ac1faa57a7e32912d76cf878f 100644
--- a/client/tarantool_checksum/tc_space.c
+++ b/client/tarantool_checksum/tc_space.c
@@ -128,7 +128,7 @@ tc_space_key_init(struct tc_space *s, tarantool_cfg_space *cs)
 
 	/* calculate primary key part count */
 	while (primary->key_field[s->pk.count]) {
-		typeof(primary->key_field[s->pk.count]) ck = primary->key_field[s->pk.count];
+		tarantool_cfg_space_index_key_field *ck = primary->key_field[s->pk.count];
 		if (ck->fieldno == -1)
 			break;
 		s->pk.count++;
@@ -147,7 +147,7 @@ tc_space_key_init(struct tc_space *s, tarantool_cfg_space *cs)
 	int kn = 0;
 	while (primary->key_field[kn]) {
 		struct tc_space_key_field *k = &s->pk.fields[kn];
-		typeof(primary->key_field[s->pk.count]) ck = primary->key_field[kn];
+		tarantool_cfg_space_index_key_field *ck = primary->key_field[kn];
 		if (ck->fieldno == -1)
 			break;
 		k->n = ck->fieldno;
diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index a21b7f0512e06c8eb61f96db5e77d67fc8f53b9f..535cd3a8c12c69b56bffd605a878a3e41f27274d 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -1,9 +1,3 @@
-#
-# Check if ObjectiveC and ObjectiveC++ compilers work
-#
-include(CMakeTestOBJCCompiler)
-#include(CMakeTestOBJCXXCompiler)
-
 #
 # Check if the same compile family is used for both C and CXX
 #
@@ -22,20 +16,24 @@ if (CMAKE_C_COMPILER_ID STREQUAL Clang)
     set(CMAKE_COMPILER_IS_GNUCXX OFF)
 endif()
 
-# Check GCC version:
-# GCC older than 4.6 is not supported.
-if (CMAKE_COMPILER_IS_GNUCC)
+# TODO: clang version is not checked
+if(CMAKE_COMPILER_IS_GNUCC)
+    # gcc and g++ >= 4.5 are supported
     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
         OUTPUT_VARIABLE CC_VERSION)
-    if (CC_VERSION VERSION_GREATER 4.4.5 OR CC_VERSION VERSION_EQUAL 4.4.5)
-        message(STATUS
-            "${CMAKE_C_COMPILER} version >= 4.4.5 -- ${CC_VERSION}")
-    else()
+    if (CC_VERSION VERSION_LESS 4.5)
         message (FATAL_ERROR
-            "${CMAKE_C_COMPILER} version should be >= 4.4.5 -- ${CC_VERSION}")
+            "${CMAKE_C_COMPILER} version should be >= 4.5 -- ${CC_VERSION}")
+    endif()
+    execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
+        OUTPUT_VARIABLE CXX_VERSION)
+    if (CXX_VERSION VERSION_LESS 4.5)
+        message (FATAL_ERROR
+            "${CMAKE_CXX_COMPILER} version should be >= 4.5 -- ${CXX_VERSION}")
     endif()
 endif()
 
+
 #
 # Perform build type specific configuration.
 #
@@ -121,8 +119,18 @@ macro(enable_tnt_compile_flags)
     # Additionally, compile it with more strict flags than the rest
     # of the code.
 
-    add_compile_flags("C;OBJC" "-std=gnu99")
-    add_compile_flags("CXX;OBJCXX" "-std=gnu++11 -fno-rtti")
+    # Set standard
+    if (CMAKE_COMPILER_IS_CLANG OR CC_VERSION VERSION_GREATER 4.7 OR
+        CC_VERSION VERSION_EQUAL 4.7)
+        add_compile_flags("C" "-std=c11")
+        add_compile_flags("CXX" "-std=c++11")
+    else()
+        add_compile_flags("C" "-std=gnu99")
+        add_compile_flags("CXX" "-std=c++0x")
+    endif()
+
+    # Disable Run-time type information
+    add_compile_flags("CXX" "-fno-rtti")
 
     add_compile_flags("C;CXX"
         "-Wall"
@@ -131,11 +139,22 @@ macro(enable_tnt_compile_flags)
         "-Wno-strict-aliasing"
     )
 
+    if (CMAKE_COMPILER_IS_GNUCXX)
+        # G++ bug. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488
+        add_compile_flags("CXX"
+            "-Wno-invalid-offsetof"
+        )
+    endif()
+
+    add_definitions("-D__STDC_FORMAT_MACROS=1")
+    add_definitions("-D__STDC_LIMIT_MACROS=1")
+    add_definitions("-D__STDC_CONSTANT_MACROS=1")
+
     # Only add -Werror if it's a debug build, done by developers using GCC.
     # Community builds should not cause extra trouble.
-    if (${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND CMAKE_COMPILER_IS_GNUCC)
-        add_compile_flags("C;CXX" "-Werror")
-    endif()
+   if (${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND CMAKE_COMPILER_IS_GNUCC)
+       add_compile_flags("C;CXX" "-Werror")
+   endif()
 endmacro(enable_tnt_compile_flags)
 
 #
@@ -149,3 +168,38 @@ check_c_compiler_flag("-Wno-unused-value" CC_HAS_WNO_UNUSED_VALUE)
 check_c_compiler_flag("-fno-strict-aliasing" CC_HAS_FNO_STRICT_ALIASING)
 check_c_compiler_flag("-Wno-comment" CC_HAS_WNO_COMMENT)
 check_c_compiler_flag("-Wno-parentheses" CC_HAS_WNO_PARENTHESES)
+
+if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNUCC)
+    set(HAVE_BUILTIN_CTZ 1)
+    set(HAVE_BUILTIN_CTZLL 1)
+    set(HAVE_BUILTIN_CLZ 1)
+    set(HAVE_BUILTIN_CLZLL 1)
+    set(HAVE_BUILTIN_POPCOUNT 1)
+    set(HAVE_BUILTIN_POPCOUNTLL 1)
+    set(HAVE_BUILTIN_BSWAP32 1)
+    set(HAVE_BUILTIN_BSWAP64 1)
+else()
+    set(HAVE_BUILTIN_CTZ 0)
+    set(HAVE_BUILTIN_CTZLL 0)
+    set(HAVE_BUILTIN_CLZ 0)
+    set(HAVE_BUILTIN_CLZLL 0)
+    set(HAVE_BUILTIN_POPCOUNT 0)
+    set(HAVE_BUILTIN_POPCOUNTLL 0)
+    set(HAVE_BUILTIN_BSWAP32 0)
+    set(HAVE_BUILTIN_BSWAP64 0)
+endif()
+
+if (NOT HAVE_BUILTIN_CTZ OR NOT HAVE_BUILTIN_CTZLL)
+    # Check if -D_GNU_SOURCE has been defined and add this flag to
+    # CMAKE_REQUIRED_DEFINITIONS in order to get check_prototype_definition work
+    get_property(var DIRECTORY PROPERTY COMPILE_DEFINITIONS)
+    list(FIND var "_GNU_SOURCE" var)
+    if (NOT var EQUAL -1)
+        set(CMAKE_REQUIRED_FLAGS "-Wno-error")
+        set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
+        check_c_source_compiles("#include <string.h>\n#include <strings.h>\nint main(void) { return ffsl(0L); }"
+            HAVE_FFSL)
+        check_c_source_compiles("#include <string.h>\n#include <strings.h>\nint main(void) { return ffsll(0UL); }"
+            HAVE_FFSLL)
+    endif()
+endif()
diff --git a/include/assoc.h b/include/assoc.h
index e5e5851fee8681ab79fdb9405108529b35602c32..fc5bb4026a3e245ef751b291766ee836a4075d20 100644
--- a/include/assoc.h
+++ b/include/assoc.h
@@ -39,7 +39,7 @@
  */
 #define mh_name _i32ptr
 struct mh_i32ptr_node_t {
-	i32 key;
+	u32 key;
 	void *val;
 };
 
@@ -55,7 +55,7 @@ struct mh_i32ptr_node_t {
  */
 #define mh_name _i64ptr
 struct mh_i64ptr_node_t {
-	i64 key;
+	u64 key;
 	void *val;
 };
 
diff --git a/include/box/box.h b/include/box/box.h
index f2e7d8bd993029842fdb6bc731331fa2a16be32c..08fa5ca882545f3081d6220e29b5c15302db5185 100644
--- a/include/box/box.h
+++ b/include/box/box.h
@@ -29,6 +29,11 @@
  * SUCH DAMAGE.
  */
 #include <util.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /*
  * Box - data storage (spaces, indexes) and query
  * processor (INSERT, UPDATE, DELETE, SELECT, Lua)
@@ -96,4 +101,8 @@ enum {
 	BOX_FIELD_MAX = UINT32_MAX
 };
 
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */
+
 #endif /* INCLUDES_TARANTOOL_BOX_H */
diff --git a/include/crc32.h b/include/crc32.h
index 1e5d0aa65e64f472d65e25d227e5e699a02e59c1..fae404eb72762cf318c59b9c4e470b7b02d8d534 100644
--- a/include/crc32.h
+++ b/include/crc32.h
@@ -31,6 +31,10 @@
 #include <sys/types.h>
 #include <util.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 typedef u_int32_t (*crc32_func)(u_int32_t crc, const unsigned char *buf, unsigned int len);
 
 /*
@@ -41,4 +45,8 @@ extern crc32_func crc32_calc;
 
 void crc32_init();
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_CRC32_H_INCLUDED */
diff --git a/include/errinj.h b/include/errinj.h
index c9e13c3ee758d659bc2144397ba4438e28f228cb..28be14dc7bd94fbbb9978a847ac7d65d42bd0bca 100644
--- a/include/errinj.h
+++ b/include/errinj.h
@@ -32,7 +32,7 @@
 #include "util.h"
 
 struct errinj {
-	char *name;
+	const char *name;
 	bool state;
 };
 
@@ -67,7 +67,7 @@ void errinj_info(struct tbuf *out);
 #endif
 
 #define ERROR_INJECT_EXCEPTION(ID) \
-	ERROR_INJECT(ID, tnt_raise(ErrorInjection, :#ID))
+	ERROR_INJECT(ID, tnt_raise(ErrorInjection, #ID))
 
 #define ERROR_INJECT_RETURN(ID) ERROR_INJECT(ID, return -1)
 
diff --git a/include/exception.h b/include/exception.h
index 7f23523e543b21ef8955f4ccf7018b6d8e40616a..3829d16cb5e64c03b081a61d970904861ea8c346 100644
--- a/include/exception.h
+++ b/include/exception.h
@@ -28,95 +28,104 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#import "object.h"
+#include "object.h"
 #include <stdarg.h>
 #include "errcode.h"
 #include "say.h"
 
-/** The base class for all exceptions.
- *
- * Note: implements garbage collection (see +alloc
- * implementation).
- */
-@interface tnt_Exception: tnt_Object {
-	@public
-		const char *file;
-		unsigned line;
-}
-+ (id) alloc;
-- (void) log;
-- (const char *) errmsg;
-@end
-
-
-/** Internal error resulting from a failed system call.
- */
-@interface SystemError: tnt_Exception {
-	@public
-		/* errno code */
-		int errnum;
-		/* error description */
-		char errmsg[TNT_ERRMSG_MAX];
-}
-
-- (id) init: (const char *)msg, ...;
-- (id) init: (int)errnum_arg :(const char *)format :(va_list)ap;
-- (void) log;
-- (const char *) errmsg;
-@end
-
-
-/** Errors that should make it to the client.
- */
-@interface ClientError: tnt_Exception {
-	@public
-		uint32_t errcode;
-		char errmsg[TNT_ERRMSG_MAX];
-}
+class Exception: public Object {
+public:
+	const char *
+	errmsg() const
+	{
+		return m_errmsg;
+	}
 
-- (id) init: (uint32_t)errcode_, ...;
-- (id) init: (uint32_t)errcode_  :(const char *)msg;
-- (id) init: (uint32_t)errcode_ args :(va_list)ap;
-- (void) log;
-- (const char *) errmsg;
-@end
+	virtual void log() const = 0;
 
+protected:
+	Exception(const char *file, unsigned line);
+	/* The copy constructor is needed for C++ throw */
+	Exception(const Exception&);
 
-/** Additionally log this error in the log file. */
-@interface LoggedError: ClientError
-- (id) init: (uint32_t)errcode, ...;
-@end
+	/* file name */
+	const char *m_file;
+	/* line number */
+	unsigned m_line;
 
+	/* error description */
+	char m_errmsg[TNT_ERRMSG_MAX];
+};
+
+class SystemError: public Exception {
+public:
+
+	int
+	errnum() const
+	{
+		return m_errnum;
+	}
+
+	virtual void log() const;
+
+protected:
+	SystemError(const char *file, unsigned line);
+
+	void
+	init(const char *format, ...);
+
+	void
+	init(const char *format, va_list ap);
+
+private:
+	/* system errno */
+	int m_errnum;
+};
+
+class ClientError: public Exception {
+public:
+	virtual void log() const;
+
+	int
+	errcode() const
+	{
+		return m_errcode;
+	}
+
+	ClientError(const char *file, unsigned line, uint32_t errcode, ...);
+	/* A special constructor for lbox_raise */
+	ClientError(const char *file, unsigned line, const char *msg,
+		    uint32_t errcode);
+private:
+	/* client errno code */
+	int m_errcode;
+};
+
+class LoggedError: public ClientError {
+public:
+	template <typename ... Args>
+	LoggedError(const char *file, unsigned line, uint32_t errcode, Args ... args)
+		: ClientError(file, line, errcode, args...)
+	{
+		/* TODO: actually calls ClientError::log */
+		log();
+	}
+};
+
+class IllegalParams: public LoggedError {
+public:
+	IllegalParams(const char *file, unsigned line, const char *msg);
+};
+
+class ErrorInjection: public LoggedError {
+public:
+	ErrorInjection(const char *file, unsigned line, const char *msg);
+};
 
-/** A handy wrapper for ER_ILLEGAL_PARAMS, which is used very
- * often.
- */
-@interface IllegalParams: LoggedError
-- (id) init: (const char *)msg;
-@end
-
-/** ER_INJECTION wrapper. */
-@interface ErrorInjection: LoggedError
-- (id) init: (const char *)msg;
-@end
-
-/**
- * A helper macro to add __FILE__ and __LINE__ information to
- * raised exceptions.
- *
- * Usage:
- *
- * tnt_raise(tnt_Exception);
- * tnt_raise(LoggedError, :"invalid argument %d", argno);
- */
 #define tnt_raise(...) tnt_raise0(__VA_ARGS__)
 #define tnt_raise0(class, ...) do {					\
 	say_debug("%s at %s:%i", #class, __FILE__, __LINE__);		\
-	class *exception = [class alloc];				\
-	exception->file = __FILE__;					\
-	exception->line = __LINE__;					\
-	[exception init __VA_ARGS__];					\
-	@throw exception;						\
+	throw class(__FILE__, __LINE__, ##__VA_ARGS__);			\
 } while (0)
 
 #endif /* TARANTOOL_EXCEPTION_H_INCLUDED */
diff --git a/include/fiber.h b/include/fiber.h
index a78a677e5fc07386dd14bf800a9598a9c9fc318b..5a2c7db5e252f0cfbb296c4a8fa40254d38494a8 100644
--- a/include/fiber.h
+++ b/include/fiber.h
@@ -38,7 +38,9 @@
 #include <util.h>
 #include "third_party/queue.h"
 
+#if defined(__cplusplus)
 #include "exception.h"
+#endif /* defined(__cplusplus) */
 #include "palloc.h"
 #include <rlist.h>
 
@@ -58,8 +60,19 @@
  * cancelled.
  */
 
-@interface FiberCancelException: tnt_Exception
-@end
+#if defined(__cplusplus)
+class FiberCancelException: public Exception {
+public:
+	FiberCancelException(const char *file, unsigned line)
+		: Exception(file, line) {
+		/* Nothing */
+	}
+
+	virtual void log() const {
+		say_debug("FiberCancelException");
+	}
+};
+#endif /* defined(__cplusplus) */
 
 struct fiber {
 #ifdef ENABLE_BACKTRACE
@@ -85,6 +98,10 @@ struct fiber {
 	struct rlist link;
 	struct rlist state;
 
+	/* This struct is considered as non-POD when compiling by g++.
+	 * You can safetly ignore all offset_of-related warnings.
+	 * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488
+	 */
 	void (*f) (va_list);
 	va_list f_data;
 	u32 flags;
@@ -124,7 +141,7 @@ void fiber_destroy_all();
 void fiber_gc(void);
 void fiber_call(struct fiber *callee, ...);
 void fiber_wakeup(struct fiber *f);
-struct fiber *fiber_find(int fid);
+struct fiber *fiber_find(uint32_t fid);
 /** Cancel a fiber. A cancelled fiber will have
  * tnt_FiberCancelException raised in it.
  *
diff --git a/include/fio.h b/include/fio.h
index f2c2a072d6ad8fdc272fc0882b1f3210575f26f0..bbece9db8a5b789ec2da6c5977f04dba6eb600ba 100644
--- a/include/fio.h
+++ b/include/fio.h
@@ -37,6 +37,10 @@
 #include <stdbool.h>
 #include <sys/uio.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 struct iovec;
 /**
  * Read up to N bytes from file into the buffer,
@@ -188,5 +192,9 @@ fio_batch_add(struct fio_batch *batch, void *row, ssize_t row_len);
 int
 fio_batch_write(struct fio_batch *batch, int fd);
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_FIO_H_INCLUDED */
 
diff --git a/include/iobuf.h b/include/iobuf.h
index e6ee150e6f926dfa25e7e90301934e2c2c703cf4..c05a41e69e385a71e931180480156ddba5c9154e 100644
--- a/include/iobuf.h
+++ b/include/iobuf.h
@@ -172,10 +172,10 @@ obuf_dup(struct obuf *obuf, const void *data, size_t size);
 static inline struct obuf_svp
 obuf_create_svp(struct obuf *buf)
 {
-	struct obuf_svp svp = {
-		.pos = buf->pos, .iov_len = buf->iov[buf->pos].iov_len,
-		.size = buf->size
-	};
+	struct obuf_svp svp;
+	svp.pos = buf->pos;
+	svp.iov_len = buf->iov[buf->pos].iov_len;
+	svp.size = buf->size;
 	return svp;
 }
 
@@ -183,7 +183,7 @@ obuf_create_svp(struct obuf *buf)
 static inline void *
 obuf_svp_to_ptr(struct obuf *buf, struct obuf_svp *svp)
 {
-	return buf->iov[svp->pos].iov_base + svp->iov_len;
+	return (char *) buf->iov[svp->pos].iov_base + svp->iov_len;
 }
 
 /** Forget anything added to output buffer after the savepoint. */
diff --git a/include/lib/bit/bit.h b/include/lib/bit/bit.h
index 6fbdf06f00b8c7d57e69d63d4d32d0d032badb1a..08274fddfa7594c8546910639801a24991418c1c 100644
--- a/include/lib/bit/bit.h
+++ b/include/lib/bit/bit.h
@@ -44,6 +44,10 @@
 #endif /* defined(HAVE_FFSL) || defined(HAVE_FFSLL) */
 #include <limits.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /** @cond false **/
 #define bit_likely(x)    __builtin_expect((x),1)
 #define bit_unlikely(x)  __builtin_expect((x),0)
@@ -471,4 +475,8 @@ bit_iterator_next(struct bit_iterator *it)
 #undef ITER_CTZ
 #undef ITER_UINT
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BIT_BIT_H_INCLUDED */
diff --git a/include/lib/bitset/bitset.h b/include/lib/bitset/bitset.h
index 3278143c02710aeac82942e33060360c45eaa2ba..ac7b97177a359124e805fb80e46ca5a672ce9f5f 100644
--- a/include/lib/bitset/bitset.h
+++ b/include/lib/bitset/bitset.h
@@ -59,6 +59,10 @@
 
 #include <lib/bit/bit.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /** @cond false */
 struct bitset_page {
 	size_t first_pos;
@@ -166,4 +170,8 @@ void
 bitset_dump(struct bitset *bitset, int verbose, FILE *stream);
 #endif /* defined(DEBUG) */
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BITSET_BITSET_H_INCLUDED */
diff --git a/include/lib/bitset/expr.h b/include/lib/bitset/expr.h
index ea6cb0b980798158e3d1fef5b44f5752e03bc183..8689f8c0cccd617ec803f28f0edbac10bd07b568 100644
--- a/include/lib/bitset/expr.h
+++ b/include/lib/bitset/expr.h
@@ -62,6 +62,10 @@
 
 #include "bitset.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /** @cond false **/
 struct bitset_expr_conj {
 	size_t size;
@@ -134,4 +138,8 @@ bitset_expr_add_conj(struct bitset_expr *expr);
 int
 bitset_expr_add_param(struct bitset_expr *expr, size_t bitset_id, bool pre_not);
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BITSET_EXPR_H_INCLUDED */
diff --git a/include/lib/bitset/index.h b/include/lib/bitset/index.h
index 877ff78d9a1716f1db0f7884c9401c372f2c651e..fd1ed792b7dba5d5e299342a02091213b6445dc1 100644
--- a/include/lib/bitset/index.h
+++ b/include/lib/bitset/index.h
@@ -114,6 +114,10 @@
 #include <lib/bitset/bitset.h>
 #include <lib/bitset/iterator.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /**
  * @brief BitsetIndex
  */
@@ -289,7 +293,7 @@ bitset_index_contains_value(struct bitset_index *index, size_t value);
  * @return number of pairs in \a index
  */
 inline size_t
-bitset_index_size(struct bitset_index *index)
+bitset_index_size(const struct bitset_index *index)
 {
 	return bitset_cardinality(index->bitsets[0]);
 }
@@ -299,4 +303,8 @@ void
 bitset_index_dump(struct bitset_index *index, int verbose, FILE *stream);
 #endif /* defined(DEBUG) */
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BITSET_INDEX_H_INCLUDED */
diff --git a/include/lib/bitset/iterator.h b/include/lib/bitset/iterator.h
index 92c143e557996abfe0ca72cf580cc69598b88fa8..6750bbabc7348a3eea9fede6d7669de7f8d200ec 100644
--- a/include/lib/bitset/iterator.h
+++ b/include/lib/bitset/iterator.h
@@ -49,6 +49,10 @@
 #include <lib/bitset/bitset.h>
 #include <lib/bitset/expr.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 /** @cond false **/
 struct bitset_iterator_conj;
 /** @endcond **/
@@ -129,4 +133,8 @@ bitset_iterator_rewind(struct bitset_iterator *it);
 size_t
 bitset_iterator_next(struct bitset_iterator *it);
 
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BITSET_ITERATOR_H_INCLUDED */
diff --git a/include/mhash.h b/include/mhash.h
index d34e83a3862d6648789e404eade099de2a000808..722a9dffc9e973c038a056336a9524595200e07d 100644
--- a/include/mhash.h
+++ b/include/mhash.h
@@ -258,6 +258,7 @@ _mh(put)(struct _mh(t) *h, const mh_node_t *node, mh_node_t **ret,
 	 mh_arg_t arg)
 {
 	mh_int_t x = mh_end(h);
+	int exist;
 	if (h->size == h->n_buckets)
 		/* no one free elements in the hash table */
 		goto put_done;
@@ -280,7 +281,7 @@ _mh(put)(struct _mh(t) *h, const mh_node_t *node, mh_node_t **ret,
 #endif
 
 	x = put_slot(h, node, arg);
-	int exist = mh_exist(h, x);
+	exist = mh_exist(h, x);
 
 	if (!exist) {
 		/* add new */
@@ -345,12 +346,12 @@ _mh(del_resize)(struct _mh(t) *h, mh_int_t x,
 struct _mh(t) *
 _mh(new)()
 {
-	struct _mh(t) *h = calloc(1, sizeof(*h));
-	h->shadow = calloc(1, sizeof(*h));
+	struct _mh(t) *h = (struct _mh(t) *) calloc(1, sizeof(*h));
+	h->shadow = (struct _mh(t) *) calloc(1, sizeof(*h));
 	h->prime = 0;
 	h->n_buckets = __ac_prime_list[h->prime];
-	h->p = calloc(h->n_buckets, sizeof(mh_node_t));
-	h->b = calloc(h->n_buckets / 16 + 1, sizeof(unsigned));
+	h->p = (mh_node_t *) calloc(h->n_buckets, sizeof(mh_node_t));
+	h->b = (mh_int_t *) calloc(h->n_buckets / 16 + 1, sizeof(unsigned));
 	h->upper_bound = h->n_buckets * MH_DENSITY;
 	return h;
 }
@@ -361,7 +362,7 @@ _mh(clear)(struct _mh(t) *h)
 	free(h->p);
 	h->prime = 0;
 	h->n_buckets = __ac_prime_list[h->prime];
-	h->p = calloc(h->n_buckets, sizeof(mh_node_t));
+	h->p = (mh_node_t *) calloc(h->n_buckets, sizeof(mh_node_t));
 	h->upper_bound = h->n_buckets * MH_DENSITY;
 }
 
@@ -437,10 +438,10 @@ _mh(start_resize)(struct _mh(t) *h, mh_int_t buckets, mh_int_t batch,
 	s->n_buckets = __ac_prime_list[h->prime];
 	s->upper_bound = s->n_buckets * MH_DENSITY;
 	s->n_dirty = 0;
-	s->p = malloc(s->n_buckets * sizeof(mh_node_t));
+	s->p = (mh_node_t *) malloc(s->n_buckets * sizeof(mh_node_t));
 	if (s->p == NULL)
 		return -1;
-	s->b = calloc(s->n_buckets / 16 + 1, sizeof(unsigned));
+	s->b = (mh_int_t *) calloc(s->n_buckets / 16 + 1, sizeof(unsigned));
 	if (s->b == NULL) {
 		free(s->p);
 		s->p = NULL;
@@ -460,11 +461,11 @@ _mh(reserve)(struct _mh(t) *h, mh_int_t size,
 
 #ifndef mh_stat
 #define mh_stat(buf, h) ({						\
-                tbuf_printf(buf, "  n_buckets: %"PRIu32 CRLF		\
-			    "  n_dirty: %"PRIu32 CRLF			\
-			    "  size: %"PRIu32 CRLF			\
-			    "  resize_cnt: %"PRIu32 CRLF		\
-			    "  resize_position: %"PRIu32 CRLF,		\
+		tbuf_printf(buf, "  n_buckets: %" PRIu32 CRLF		\
+			    "  n_dirty: %" PRIu32 CRLF			\
+			    "  size: %" PRIu32 CRLF			\
+			    "  resize_cnt: %" PRIu32 CRLF		\
+			    "  resize_position: %" PRIu32 CRLF,		\
 			    h->n_buckets,				\
 			    h->n_dirty,					\
 			    h->size,					\
diff --git a/include/object.h b/include/object.h
index 643980a081fa77d8dd0175196160042be7018a13..cf97d59c5c8828a5d851d4d2e8361964476c5884 100644
--- a/include/object.h
+++ b/include/object.h
@@ -28,14 +28,26 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <objc/runtime.h>
 
-@interface tnt_Object {
-	Class isa;
-}
-+ (id) alloc;
-- (id) init;
-- (void) free;
-- (void) subclassResponsibility: (SEL) cmd;
-@end
+class Object {
+public:
+	Object() {
+		/* Nothing */
+	}
+
+protected:
+	/*
+	 * Explicitly disable the copy constructor and the assignment operato
+	 */
+	Object(const Object&)
+	{
+		/* Nothing */
+	}
+
+	Object& operator=(const Object&)
+	{
+		return *this;
+	}
+};
+
 #endif /* TARANTOOL_OBJECT_H_INCLUDED */
diff --git a/include/palloc.h b/include/palloc.h
index d945aa5552116b4f81de27ee1e261a895667a8bb..0557cd620f49b867b90f2fbbea83c4d37b4bb1ca 100644
--- a/include/palloc.h
+++ b/include/palloc.h
@@ -32,6 +32,10 @@
 #include <stdint.h>
 #include "util.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 #define PALLOC_POOL_NAME_MAXLEN 30
 
 struct tbuf;
@@ -57,4 +61,8 @@ size_t palloc_allocated(struct palloc_pool *);
 
 void palloc_stat(struct tbuf *buf);
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_PALLOC_H_INCLUDED */
diff --git a/include/pickle.h b/include/pickle.h
index 8f3e6340a10314bf9f5bc1eb52bae081ea8cadbf..0e35d4c9788da31d62fa6433ca3fc6f0dba48310 100644
--- a/include/pickle.h
+++ b/include/pickle.h
@@ -43,7 +43,7 @@
 static inline uint32_t
 load_u32(const void **data)
 {
-	const uint32_t *b = *data;
+	const uint32_t *b = (const uint32_t *) *data;
 	*data= b + 1;
 	return *b;
 }
@@ -52,27 +52,27 @@ static inline uint32_t
 load_varint32(const void **data)
 {
 	assert(data != NULL && *data != NULL);
-	const uint8_t *b = *data;
+	const uint8_t *b = (const uint8_t *) *data;
 
 	if (!(b[0] & 0x80)) {
-		*data += 1;
+		*data = (char *) *data + 1;
 		return (b[0] & 0x7f);
 	}
 	if (!(b[1] & 0x80)) {
-		*data += 2;
+		*data = (char *) *data + 2;
 		return (b[0] & 0x7f) << 7 | (b[1] & 0x7f);
 	}
 	if (!(b[2] & 0x80)) {
-		*data += 3;
+		*data = (char *) *data + 3;
 		return (b[0] & 0x7f) << 14 | (b[1] & 0x7f) << 7 | (b[2] & 0x7f);
 	}
 	if (!(b[3] & 0x80)) {
-		*data += 4;
+		*data = (char *) *data + 4;
 		return (b[0] & 0x7f) << 21 | (b[1] & 0x7f) << 14 |
 			(b[2] & 0x7f) << 7 | (b[3] & 0x7f);
 	}
 	if (!(b[4] & 0x80)) {
-		*data += 5;
+		*data = (char *) *data + 5;
 		return (b[0] & 0x7f) << 28 | (b[1] & 0x7f) << 21 |
 			(b[2] & 0x7f) << 14 | (b[3] & 0x7f) << 7 | (b[4] & 0x7f);
 	}
@@ -84,63 +84,63 @@ static inline uint32_t
 pick_varint32(const void **data, const void *end)
 {
 	assert(data != NULL && *data != NULL);
-	const uint8_t *b = *data;
-	ssize_t size = end - *data;
+	const uint8_t *b = (const uint8_t *) *data;
+	ssize_t size = (const char *) end - (const char * )*data;
 
 	if (unlikely(size < 1))
-		tnt_raise(IllegalParams, :"varint is too short (expected 1+ bytes)");
+		tnt_raise(IllegalParams, "varint is too short (expected 1+ bytes)");
 
 	if (!(b[0] & 0x80)) {
-		*data += 1;
+		*data = (char *) *data + 1;
 		return (b[0] & 0x7f);
 	}
 
 	if (unlikely(size < 2))
-		tnt_raise(IllegalParams, :"varint is too short (expected 2+ bytes)");
+		tnt_raise(IllegalParams, "varint is too short (expected 2+ bytes)");
 
 	if (!(b[1] & 0x80)) {
-		*data += 2;
+		*data = (char *) *data + 2;
 		return (b[0] & 0x7f) << 7 | (b[1] & 0x7f);
 	}
 
 	if (unlikely(size < 3))
-		tnt_raise(IllegalParams, :"BER int is too short (expected 3+ bytes)");
+		tnt_raise(IllegalParams, "BER int is too short (expected 3+ bytes)");
 
 	if (!(b[2] & 0x80)) {
-		*data += 3;
+		*data = (char *) *data + 3;
 		return (b[0] & 0x7f) << 14 | (b[1] & 0x7f) << 7 | (b[2] & 0x7f);
 	}
 
 	if (unlikely(size < 4))
-		tnt_raise(IllegalParams, :"BER int is too short (expected 4+ bytes)");
+		tnt_raise(IllegalParams, "BER int is too short (expected 4+ bytes)");
 
 	if (!(b[3] & 0x80)) {
-		*data += 4;
+		*data = (char *) *data + 4;
 		return (b[0] & 0x7f) << 21 | (b[1] & 0x7f) << 14 |
 			(b[2] & 0x7f) << 7 | (b[3] & 0x7f);
 	}
 
 	if (unlikely(size < 5))
-		tnt_raise(IllegalParams, :"BER int is too short (expected 5+ bytes)");
+		tnt_raise(IllegalParams, "BER int is too short (expected 5+ bytes)");
 
 	if (!(b[4] & 0x80)) {
-		*data += 5;
+		*data = (char *) *data + 5;
 		return (b[0] & 0x7f) << 28 | (b[1] & 0x7f) << 21 |
 			(b[2] & 0x7f) << 14 | (b[3] & 0x7f) << 7 | (b[4] & 0x7f);
 	}
 
-	tnt_raise(IllegalParams, :"incorrect BER integer format");
+	tnt_raise(IllegalParams, "incorrect BER integer format");
 }
 
 #define pick_u(bits)						\
 static inline uint##bits##_t					\
 pick_u##bits(const void **begin, const void *end)		\
 {								\
-	if (end - *begin < (bits)/8)				\
+	if ((const char *) end - (const char *) *begin < (bits)/8)				\
 		tnt_raise(IllegalParams,			\
-			  :"packet too short (expected "#bits" bits)");\
+			  "packet too short (expected "#bits" bits)");\
 	uint##bits##_t r = *(uint##bits##_t *)*begin;		\
-	*begin += (bits)/8;					\
+	*begin = (const char *) *begin + (bits)/8;		\
 	return r;						\
 }
 
@@ -153,10 +153,10 @@ static inline const void *
 pick_str(const void **data, const void *end, uint32_t size)
 {
 	const void *str = *data;
-	if (str + size > end)
+	if ((const char *) str + size > (const char *) end)
 		tnt_raise(IllegalParams,
-			  :"packet too short (expected a field)");
-	*data += size;
+			  "packet too short (expected a field)");
+	*data = (char *) *data + size;
 	return str;
 }
 
@@ -183,7 +183,7 @@ pick_field_u32(const void **data, const void *end)
 	uint32_t size = pick_varint32(data, end);
 	if (size != sizeof(uint32_t))
 		tnt_raise(IllegalParams,
-			  :"incorrect packet format (expected a 32-bit int)");
+			  "incorrect packet format (expected a 32-bit int)");
 	return *(uint32_t *) pick_str(data, end, size);
 }
 
@@ -197,7 +197,7 @@ valid_tuple(const void *data, const void *end, uint32_t field_count)
 	for (int i = 0; i < field_count; i++)
 		pick_field(&data, end);
 
-	return data - start;
+	return (const char *) data - (const char *) start;
 }
 
 /**
@@ -211,9 +211,9 @@ tuple_range_size(const void **begin, const void *end, size_t count)
 	const void *start = *begin;
 	while (*begin < end && count-- > 0) {
 		size_t len = load_varint32(begin);
-		*begin += len;
+		*begin = (char *) *begin + len;
 	}
-	return *begin - start;
+	return (const char *) *begin - (const char *) start;
 }
 
 static inline size_t
@@ -234,7 +234,7 @@ varint32_sizeof(uint32_t value)
 static inline void *
 pack_varint32(void *buf, uint32_t value)
 {
-	uint8_t *target = buf;
+	uint8_t *target = (uint8_t *) buf;
 	if (value >= (1 << 7)) {
 		if (value >= (1 << 14)) {
 			if (value >= (1 << 21)) {
@@ -254,7 +254,7 @@ pack_varint32(void *buf, uint32_t value)
 static inline void *
 pack_lstr(void *buf, const void *str, uint32_t len)
 {
-	return memcpy(pack_varint32(buf, len), str, len) + len;
+	return (char *) memcpy(pack_varint32(buf, len), str, len) + len;
 }
 
 #endif /* TARANTOOL_PICKLE_H_INCLUDED */
diff --git a/include/recovery.h b/include/recovery.h
index 11bb87090d8cfbe5e9ebadc73b59bbaf3f94f1f4..b04993b6a418d51381d2ba9b46a8313515779a1e 100644
--- a/include/recovery.h
+++ b/include/recovery.h
@@ -34,6 +34,10 @@
 #include "util.h"
 #include "tarantool_ev.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 struct fiber;
 struct tbuf;
 
@@ -144,4 +148,8 @@ void snapshot_write_row(struct log_io *i, struct fio_batch *batch,
 void snapshot_save(struct recovery_state *r,
 		   void (*loop) (struct log_io *, struct fio_batch *));
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_RECOVERY_H_INCLUDED */
diff --git a/include/replication.h b/include/replication.h
index 48771597828a3d20f48a820513efc5192178e0ab..608cafe73d96b56084f84be0a160059bceba036c 100644
--- a/include/replication.h
+++ b/include/replication.h
@@ -55,7 +55,7 @@ replication_prefork();
  * @return None. Panics and exits on error.
  */
 void
-replication_init();
+replication_init(const char *bind_ipaddr, int replication_port);
 
 #endif // TARANTOOL_REPLICATION_H_INCLUDED
 
diff --git a/include/rlist.h b/include/rlist.h
index a3d10d36004b24b7781b7384f5589885bf050aed..1756efb5c07bf9404d35b63371352c9dd9acd00c 100644
--- a/include/rlist.h
+++ b/include/rlist.h
@@ -29,6 +29,15 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+#ifndef typeof
+/* TODO: 'typeof' is a GNU extension */
+#define typeof __typeof__
+#endif
+
 /**
  * list entry and head structure
  */
@@ -266,4 +275,9 @@ delete from one list and add_tail as another's head
 		item = rlist_prev_entry((item), member))
 
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+
 #endif /* TARANTOOL_RLIST_H_INCLUDED */
diff --git a/include/rope.h b/include/rope.h
index 8b799afcc6b3118d71c7f5534475b215208197eb..bbebff7a02c0701d1aeb78f46fd90b1f9fce945c 100644
--- a/include/rope.h
+++ b/include/rope.h
@@ -31,6 +31,10 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 typedef unsigned int rsize_t;
 typedef int rssize_t;
 typedef void *(*rope_split_func)(void *, size_t, size_t);
@@ -45,9 +49,9 @@ struct rope_node {
 	int height;
 	/** Subtree size. */
 	rsize_t tree_size;
-        /* Substring size. */
+	/* Substring size. */
 	rsize_t leaf_size;
-        /* Substring. */
+	/* Substring. */
 	void *data;
 	/* Left (0) and right (1) links */
 	struct rope_node *link[2];
@@ -210,8 +214,8 @@ rope_iter_create(struct rope_iter *it, struct rope *rope)
 static inline struct rope_iter *
 rope_iter_new(struct rope *rope)
 {
-	struct rope_iter *it = rope->alloc(rope->alloc_ctx,
-					     sizeof(struct rope_iter));
+	struct rope_iter *it = (struct rope_iter *)
+			rope->alloc(rope->alloc_ctx, sizeof(struct rope_iter));
 
 	if (it == NULL)
 		return NULL;
@@ -255,4 +259,8 @@ rope_check(struct rope *rope);
 void
 rope_pretty_print(struct rope *rope, void (*print_leaf)(void *, size_t));
 
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */
+
 #endif /* INCLUDES_TARANTOOL_ROPE_H */
diff --git a/include/say.h b/include/say.h
index cbe97193e05051c9953b3da42f4704f2286c76cc..02df38ed0ea34db26713d7dedcda4318fa9b1ee7 100644
--- a/include/say.h
+++ b/include/say.h
@@ -34,6 +34,10 @@
 
 #include <util.h> /* for FORMAT_PRINTF */
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 enum say_level {
 	S_FATAL,		/* do not this value use directly */
 	S_ERROR,
@@ -67,5 +71,8 @@ void _say(int level, const char *filename, int line, const char *error,
 #define say_debug(...)			say(S_DEBUG, NULL, __VA_ARGS__)
 
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
 
 #endif /* TARANTOOL_SAY_H_INCLUDED */
diff --git a/include/scoped_guard.h b/include/scoped_guard.h
new file mode 100644
index 0000000000000000000000000000000000000000..a141737acc915f2d5592d9d5f8984aee49cb9af6
--- /dev/null
+++ b/include/scoped_guard.h
@@ -0,0 +1,71 @@
+#ifndef TARANTOOL_SCOPED_GUARD_H_INCLUDED
+#define TARANTOOL_SCOPED_GUARD_H_INCLUDED
+
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "object.h"
+
+template <typename Functor>
+class ScopedGuard: public Object {
+public:
+	explicit ScopedGuard(const Functor& fun)
+		: m_fun(fun), m_active(true) {
+		/* nothing */
+	}
+
+	ScopedGuard(ScopedGuard&& guard)
+		: m_fun(guard.m_fun), m_active(true) {
+		guard.m_active = false;
+	}
+
+	~ScopedGuard()
+	{
+		if (!m_active)
+			return;
+
+		m_fun();
+	}
+
+private:
+	ScopedGuard(const ScopedGuard&) = delete;
+	ScopedGuard& operator=(const ScopedGuard&) = delete;
+
+	const Functor& m_fun;
+	bool m_active;
+};
+
+template <typename Functor>
+inline ScopedGuard<Functor>
+make_scoped_guard(const Functor& guard)
+{
+	return ScopedGuard<Functor>(guard);
+}
+
+#endif /* TARANTOOL_SCOPED_GUARD_H_INCLUDED */
diff --git a/include/sio.h b/include/sio.h
index ba7ad0ab70132dc80b11b3429d38d56c7a68410b..e67b7dc83a12a4d419e29e0cbaf6b01524ee6038 100644
--- a/include/sio.h
+++ b/include/sio.h
@@ -42,10 +42,11 @@
 
 enum { SERVICE_NAME_MAXLEN = 32 };
 
-@interface SocketError: SystemError
-- (id) init: (int) fd in: (const char *) format: (va_list) ap;
-- (id) init: (int) fd in: (const char *) format, ...;
-@end
+class SocketError: public SystemError {
+public:
+	SocketError(const char *file, unsigned line, int fd,
+		    const char *format, ...);
+};
 
 const char *sio_socketname(int fd);
 int sio_socket(int domain, int type, int protocol);
@@ -117,7 +118,7 @@ static inline void
 sio_add_to_iov(struct iovec *iov, ssize_t size)
 {
 	iov->iov_len += size;
-	iov->iov_base -= size;
+	iov->iov_base = (char *) iov->iov_base - size;
 }
 
 #endif /* TARANTOOL_SIO_H_INCLUDED */
diff --git a/include/stat.h b/include/stat.h
index 191a103e32b9b0e1a3802ad5f8fd5f5da9972ed8..478eeb4f4c9f2f4dc3312d1e2b40b2533ccaf347 100644
--- a/include/stat.h
+++ b/include/stat.h
@@ -34,7 +34,7 @@ void stat_init(void);
 void stat_free(void);
 void stat_cleanup(int base, size_t max_idx);
 int stat_register(const char **name, size_t count);
-int stat_max_name_len;
+extern int stat_max_name_len;
 
 void stat_collect(int base, int name, i64 value);
 
diff --git a/include/tarantool.h b/include/tarantool.h
index b9eda2655216e50cdf2ad03e6ac529439826f155..c28fe745393bfd2aee4ce51c9e1ad5e80210ba60 100644
--- a/include/tarantool.h
+++ b/include/tarantool.h
@@ -31,6 +31,10 @@
 #include <stdbool.h>
 #include <util.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 struct tarantool_cfg;
 struct tbuf;
 
@@ -52,4 +56,12 @@ char **init_set_proc_title(int argc, char **argv);
 void free_proc_title(int argc, char **argv);
 void set_proc_title(const char *format, ...);
 void title(const char *fmt, ...);
+
+#define DEFAULT_CFG_FILENAME "tarantool.cfg"
+#define DEFAULT_CFG SYSCONF_DIR "/" DEFAULT_CFG_FILENAME
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_H_INCLUDED */
diff --git a/include/tbuf.h b/include/tbuf.h
index 50844d28ea3e29cabf9e0fa38482b658cf24c272..89f1654f18c8b24597614055ae50dc0b59347dc0 100644
--- a/include/tbuf.h
+++ b/include/tbuf.h
@@ -34,13 +34,17 @@
 
 #include <util.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 struct tbuf {
 	/* Used space in the buffer. */
 	u32 size;
 	/* Total allocated buffer capacity. */
 	u32 capacity;
 	/* Allocated buffer. */
-	void *data;
+	char *data;
 	struct palloc_pool *pool;
 };
 
@@ -60,7 +64,7 @@ static inline void tbuf_append(struct tbuf *b, const void *data, size_t len)
 	tbuf_ensure(b, len + 1); /* +1 for trailing '\0' */
 	memcpy(b->data + b->size, data, len);
 	b->size += len;
-	*(((char *)b->data) + b->size) = '\0';
+	*((b->data) + b->size) = '\0';
 }
 
 static inline char *
@@ -94,4 +98,9 @@ void tbuf_printf(struct tbuf *b, const char *format, ...)
 	__attribute__ ((format(FORMAT_PRINTF, 2, 3)));
 
 char *tbuf_to_hex(const struct tbuf *x);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_TBUF_H_INCLUDED */
diff --git a/include/util.h b/include/util.h
index aa78f578cf3ed418b9daa2f86da06ff1f688a309..ea73f53ac3f32865cd92d39cbb0929345fa76879 100644
--- a/include/util.h
+++ b/include/util.h
@@ -34,6 +34,12 @@
 #include <unistd.h>
 #include <inttypes.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+#define restrict __restrict__
+
 #ifndef NDEBUG
 #define TRASH(ptr) memset(ptr, '#', sizeof(*ptr))
 #else
@@ -48,11 +54,27 @@
 /* Macros to define enum and corresponding strings. */
 #define ENUM0_MEMBER(s, ...) s,
 #define ENUM_MEMBER(s, v, ...) s = v,
-#define ENUM_STRS_MEMBER(s, v, ...) [s] = #s,
 #define ENUM0(enum_name, enum_members) enum enum_name {enum_members(ENUM0_MEMBER) enum_name##_MAX}
 #define ENUM(enum_name, enum_members) enum enum_name {enum_members(ENUM_MEMBER) enum_name##_MAX}
+#if defined(__cplusplus)
+#define ENUM_STRS_MEMBER(s, v, ...) names[s] = #s;
+/* A special hack to emulate C99 designated initializers */
+#define STRS(enum_name, enum_members)					\
+	const char *enum_name##_strs[enum_name##_MAX];			\
+	namespace {							\
+		const struct enum_name##_strs_init {			\
+			enum_name##_strs_init(const char **names) {	\
+				memset(names, 0, sizeof(*names) *	\
+				       enum_name##_MAX);		\
+				enum_members(ENUM_STRS_MEMBER)		\
+			}						\
+		}  enum_name##_strs_init(enum_name##_strs);		\
+	}
+#else /* !defined(__cplusplus) */
+#define ENUM_STRS_MEMBER(s, v, ...) [s] = #s,
 #define STRS(enum_name, enum_members) \
-	const char *enum_name##_strs[enum_name##_MAX + 1] = {enum_members(ENUM_STRS_MEMBER) '\0'}
+	const char *enum_name##_strs[(unsigned) enum_name##_MAX + 1] = {enum_members(ENUM_STRS_MEMBER) 0}
+#endif
 #define STR2ENUM(enum_name, str) ((enum enum_name) strindex(enum_name##_strs, str, enum_name##_MAX))
 
 uint32_t
@@ -169,4 +191,8 @@ void *
 memrchr(const void *s, int c, size_t n);
 #endif /* HAVE_MEMRCHR */
 
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_UTIL_H_INCLUDED */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8028d32837b35d330a3a76099fd94adccb84270d..add443c2addf7cc748f6fc63f5dc25bc5ee1df9b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,41 +17,41 @@ if (CMAKE_COMPILER_IS_GNUCC)
 endif()
 
 #
-# Build admin.m from admin.rl, but only if admin.rl was changed.
-# The same applies to memcached.m/memcached.rl.
-# We track admin.m and memcached.m in revision control, and thus do not
+# Build admin.cc from admin.rl, but only if admin.rl was changed.
+# The same applies to memcached.cc/memcached.rl.
+# We track admin.cc and memcached.cc in revision control, and thus do not
 # require engineers who do not modify .rl files to have Ragel
 # installed.
 #
-add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/admin.m
+add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/admin.cc
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-    COMMAND ${RAGEL} -G2 src/admin.rl -o src/admin.m
+    COMMAND ${RAGEL} -G2 src/admin.rl -o src/admin.cc
     DEPENDS ${CMAKE_SOURCE_DIR}/src/admin.rl)
 
-add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/memcached-grammar.m
+add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/src/memcached-grammar.cc
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     COMMAND ${RAGEL} -G2 src/memcached-grammar.rl
-                     -o src/memcached-grammar.m
+                     -o src/memcached-grammar.cc
     DEPENDS ${CMAKE_SOURCE_DIR}/src/memcached-grammar.rl)
 
-add_custom_target(generate_admin_m DEPENDS ${CMAKE_SOURCE_DIR}/src/admin.m)
-add_custom_target(generate_memcached_grammar_m DEPENDS
-    ${CMAKE_SOURCE_DIR}/src/memcached-grammar.m)
+add_custom_target(generate_admin_m DEPENDS ${CMAKE_SOURCE_DIR}/src/admin.cc)
+add_custom_target(generate_memcached_grammar_cc DEPENDS
+    ${CMAKE_SOURCE_DIR}/src/memcached-grammar.cc)
 
-# do not randomly try to re-generate admin.m or memcached-grammar.m
+# do not randomly try to re-generate admin.cc or memcached-grammar.cc
 # after a fresh checkout/branch switch.
 execute_process(COMMAND ${CMAKE_COMMAND} -E touch_nocreate
-    ${CMAKE_SOURCE_DIR}/src/admin.m
-    ${CMAKE_SOURCE_DIR}/src/memcached-grammar.m)
+    ${CMAKE_SOURCE_DIR}/src/admin.cc
+    ${CMAKE_SOURCE_DIR}/src/memcached-grammar.cc)
 
-set_source_files_properties(${CMAKE_SOURCE_DIR}/src/memcached-grammar.m
+set_source_files_properties(${CMAKE_SOURCE_DIR}/src/memcached-grammar.cc
     PROPERTIES HEADER_FILE_ONLY true)
 
-set_source_files_properties(memcached.m
+set_source_files_properties(memcached.cc
     PROPERTIES COMPILE_FLAGS "-Wno-uninitialized")
 
 #
-# Do not clean admin.m, memcached.m or other
+# Do not clean admin.cc, memcached.cc or other
 # generated files in 'make clean' -- they are under
 # revision control.
 #
@@ -61,55 +61,57 @@ set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM true)
 # Used by modules.
 #
 set (recompiled_sources
-     ${CMAKE_SOURCE_DIR}/src/tarantool.m
-     ${CMAKE_SOURCE_DIR}/src/lua/init.m
-     ${CMAKE_SOURCE_DIR}/src/say.m
-     ${CMAKE_SOURCE_DIR}/src/assoc.m
-     ${CMAKE_SOURCE_DIR}/src/replication.m
-     ${CMAKE_SOURCE_DIR}/src/memcached.m
-     ${CMAKE_SOURCE_DIR}/src/fiber.m)
+     ${CMAKE_SOURCE_DIR}/src/tarantool.cc
+     ${CMAKE_SOURCE_DIR}/src/opts.c
+     ${CMAKE_SOURCE_DIR}/src/lua/init.cc
+     ${CMAKE_SOURCE_DIR}/src/say.cc
+     ${CMAKE_SOURCE_DIR}/src/assoc.cc
+     ${CMAKE_SOURCE_DIR}/src/replication.cc
+     ${CMAKE_SOURCE_DIR}/src/memcached.cc
+     ${CMAKE_SOURCE_DIR}/src/fiber.cc)
 
 set (common_sources
-     tbuf.m
-     palloc.m
-     util.m
-     sio.m
-     evio.m
-     coio.m
-     coeio.m
-     iobuf.m
-     coio_buf.m
-     salloc.m
-     pickle.m
-     coro.m
-     stat.m
-     log_io.m
-     recovery.m
-     admin.m
-     cpu_feature.m
-     replica.m
-     iproto.m
-     session.m
-     object.m
-     exception.m
+     tbuf.c
+     palloc.cc
+     util.c
+     scoped_guard.cc
+     sio.cc
+     evio.cc
+     coio.cc
+     coeio.cc
+     iobuf.cc
+     coio_buf.cc
+     salloc.cc
+     pickle.cc
+     coro.cc
+     stat.cc
+     log_io.cc
+     recovery.cc
+     admin.cc
+     cpu_feature.c
+     replica.cc
+     iproto.cc
+     session.cc
+     object.cc
+     exception.cc
      errcode.c
-     errinj.m
+     errinj.cc
      fio.c
      crc32.c
      rope.c
-     ipc.m
-     lua/info.m
-     lua/stat.m
-     lua/slab.m
-     lua/uuid.m
-     lua/lua_ipc.m
-     lua/lua_socket.m
-     lua/session.m
-     lua/cjson.m
+     ipc.cc
+     lua/info.cc
+     lua/stat.cc
+     lua/slab.cc
+     lua/uuid.cc
+     lua/lua_ipc.cc
+     lua/lua_socket.cc
+     lua/session.cc
+     lua/cjson.cc
 )
 
 if (ENABLE_TRACE)
-    set (common_sources ${common_sources} trace.m)
+    set (common_sources ${common_sources} trace.c)
 endif()
 
 set_source_files_compile_flags(${common_sources})
@@ -125,7 +127,6 @@ list(APPEND common_libraries
     ${LIBGOPT_LIBRARIES}
     ${LIBCJSON_LIBRARIES}
     ${LUAJIT_LIB}
-    ${LIBOBJC_LIBRARIES}
     misc
 )
 
diff --git a/src/admin.m b/src/admin.cc
similarity index 94%
rename from src/admin.m
rename to src/admin.cc
index 361eebaa919932ce01c442cfc7c20889c4c7fadc..d0f64ebaeb589333f05f6f4b341d86694b088b0e 100644
--- a/src/admin.m
+++ b/src/admin.cc
@@ -47,11 +47,15 @@
 #include <errinj.h>
 #include "coio_buf.h"
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+
 #include "box/box.h"
 #include "session.h"
+#include "scoped_guard.h"
 
 static const char *help =
 	"available commands:" CRLF
@@ -73,7 +77,7 @@ static const char *help =
 static const char *unknown_command = "unknown command. try typing help." CRLF;
 
 
-#line 77 "src/admin.m"
+#line 81 "src/admin.cc"
 static const int admin_start = 1;
 static const int admin_first_final = 135;
 static const int admin_error = 0;
@@ -81,7 +85,7 @@ static const int admin_error = 0;
 static const int admin_en_main = 1;
 
 
-#line 76 "src/admin.rl"
+#line 80 "src/admin.rl"
 
 
 struct salloc_stat_admin_cb_ctx {
@@ -92,7 +96,7 @@ struct salloc_stat_admin_cb_ctx {
 static int
 salloc_stat_admin_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
 {
-	struct salloc_stat_admin_cb_ctx *ctx = cb_ctx;
+	struct salloc_stat_admin_cb_ctx *ctx = (struct salloc_stat_admin_cb_ctx *) cb_ctx;
 
 	tbuf_printf(ctx->out,
 		    "     - { item_size: %- 5i, slabs: %- 3i, items: %- 11" PRIi64
@@ -168,7 +172,7 @@ tarantool_info(struct tbuf *out)
 	tbuf_printf(out, "  lsn: %" PRIi64 CRLF,
 		    recovery_state->confirmed_lsn);
 	tbuf_printf(out, "  recovery_lag: %.3f" CRLF,
-		    recovery_state->remote ? 
+		    recovery_state->remote ?
 		    recovery_state->remote->recovery_lag : 0);
 	tbuf_printf(out, "  recovery_last_update: %.3f" CRLF,
 		    recovery_state->remote ?
@@ -183,7 +187,7 @@ tarantool_info(struct tbuf *out)
 static int
 show_stat_item(const char *name, int rps, i64 total, void *ctx)
 {
-	struct tbuf *buf = ctx;
+	struct tbuf *buf = (struct tbuf *) ctx;
 	int name_len = strlen(name);
 	tbuf_printf(buf,
 		    "  %s:%*s{ rps: %- 6i, total: %- 12" PRIi64 " }" CRLF,
@@ -209,7 +213,7 @@ admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
 	char *strstart, *strend;
 	bool state;
 
-	while ((pe = memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
+	while ((pe = (char *) memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
 		if (coio_bread(coio, in, 1) <= 0)
 			return -1;
 	}
@@ -218,12 +222,12 @@ admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
 	p = in->pos;
 
 	
-#line 222 "src/admin.m"
+#line 226 "src/admin.cc"
 	{
 	cs = admin_start;
 	}
 
-#line 227 "src/admin.m"
+#line 231 "src/admin.cc"
 	{
 	if ( p == pe )
 		goto _test_eof;
@@ -286,15 +290,15 @@ case 6:
 	}
 	goto st0;
 tr13:
-#line 309 "src/admin.rl"
+#line 313 "src/admin.rl"
 	{slab_validate(); ok(out);}
 	goto st135;
 tr20:
-#line 297 "src/admin.rl"
+#line 301 "src/admin.rl"
 	{return -1;}
 	goto st135;
 tr25:
-#line 224 "src/admin.rl"
+#line 228 "src/admin.rl"
 	{
 			start(out);
 			tbuf_append(out, help, strlen(help));
@@ -302,9 +306,9 @@ case 6:
 		}
 	goto st135;
 tr36:
-#line 283 "src/admin.rl"
+#line 287 "src/admin.rl"
 	{strend = p;}
-#line 230 "src/admin.rl"
+#line 234 "src/admin.rl"
 	{
 			strstart[strend-strstart]='\0';
 			start(out);
@@ -313,7 +317,7 @@ case 6:
 		}
 	goto st135;
 tr43:
-#line 237 "src/admin.rl"
+#line 241 "src/admin.rl"
 	{
 			if (reload_cfg(err))
 				fail(out, err);
@@ -322,11 +326,11 @@ case 6:
 		}
 	goto st135;
 tr67:
-#line 307 "src/admin.rl"
+#line 311 "src/admin.rl"
 	{coredump(60); ok(out);}
 	goto st135;
 tr76:
-#line 244 "src/admin.rl"
+#line 248 "src/admin.rl"
 	{
 			int ret = snapshot();
 
@@ -341,9 +345,9 @@ case 6:
 		}
 	goto st135;
 tr98:
-#line 293 "src/admin.rl"
+#line 297 "src/admin.rl"
 	{ state = false; }
-#line 257 "src/admin.rl"
+#line 261 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -355,9 +359,9 @@ case 6:
 		}
 	goto st135;
 tr101:
-#line 292 "src/admin.rl"
+#line 296 "src/admin.rl"
 	{ state = true; }
-#line 257 "src/admin.rl"
+#line 261 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -369,7 +373,7 @@ case 6:
 		}
 	goto st135;
 tr117:
-#line 212 "src/admin.rl"
+#line 216 "src/admin.rl"
 	{
 			start(out);
 			show_cfg(out);
@@ -377,15 +381,15 @@ case 6:
 		}
 	goto st135;
 tr131:
-#line 300 "src/admin.rl"
+#line 304 "src/admin.rl"
 	{start(out); fiber_info(out); end(out);}
 	goto st135;
 tr137:
-#line 299 "src/admin.rl"
+#line 303 "src/admin.rl"
 	{start(out); tarantool_info(out); end(out);}
 	goto st135;
 tr146:
-#line 218 "src/admin.rl"
+#line 222 "src/admin.rl"
 	{
 			start(out);
 			errinj_info(out);
@@ -393,33 +397,33 @@ case 6:
 		}
 	goto st135;
 tr152:
-#line 303 "src/admin.rl"
+#line 307 "src/admin.rl"
 	{start(out); palloc_stat(out); end(out);}
 	goto st135;
 tr160:
-#line 302 "src/admin.rl"
+#line 306 "src/admin.rl"
 	{start(out); show_slab(out); end(out);}
 	goto st135;
 tr164:
-#line 304 "src/admin.rl"
+#line 308 "src/admin.rl"
 	{start(out); show_stat(out);end(out);}
 	goto st135;
 st135:
 	if ( ++p == pe )
 		goto _test_eof135;
 case 135:
-#line 412 "src/admin.m"
+#line 416 "src/admin.cc"
 	goto st0;
 tr14:
-#line 309 "src/admin.rl"
+#line 313 "src/admin.rl"
 	{slab_validate(); ok(out);}
 	goto st7;
 tr21:
-#line 297 "src/admin.rl"
+#line 301 "src/admin.rl"
 	{return -1;}
 	goto st7;
 tr26:
-#line 224 "src/admin.rl"
+#line 228 "src/admin.rl"
 	{
 			start(out);
 			tbuf_append(out, help, strlen(help));
@@ -427,9 +431,9 @@ case 135:
 		}
 	goto st7;
 tr37:
-#line 283 "src/admin.rl"
+#line 287 "src/admin.rl"
 	{strend = p;}
-#line 230 "src/admin.rl"
+#line 234 "src/admin.rl"
 	{
 			strstart[strend-strstart]='\0';
 			start(out);
@@ -438,7 +442,7 @@ case 135:
 		}
 	goto st7;
 tr44:
-#line 237 "src/admin.rl"
+#line 241 "src/admin.rl"
 	{
 			if (reload_cfg(err))
 				fail(out, err);
@@ -447,11 +451,11 @@ case 135:
 		}
 	goto st7;
 tr68:
-#line 307 "src/admin.rl"
+#line 311 "src/admin.rl"
 	{coredump(60); ok(out);}
 	goto st7;
 tr77:
-#line 244 "src/admin.rl"
+#line 248 "src/admin.rl"
 	{
 			int ret = snapshot();
 
@@ -466,9 +470,9 @@ case 135:
 		}
 	goto st7;
 tr99:
-#line 293 "src/admin.rl"
+#line 297 "src/admin.rl"
 	{ state = false; }
-#line 257 "src/admin.rl"
+#line 261 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -480,9 +484,9 @@ case 135:
 		}
 	goto st7;
 tr102:
-#line 292 "src/admin.rl"
+#line 296 "src/admin.rl"
 	{ state = true; }
-#line 257 "src/admin.rl"
+#line 261 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -494,7 +498,7 @@ case 135:
 		}
 	goto st7;
 tr118:
-#line 212 "src/admin.rl"
+#line 216 "src/admin.rl"
 	{
 			start(out);
 			show_cfg(out);
@@ -502,15 +506,15 @@ case 135:
 		}
 	goto st7;
 tr132:
-#line 300 "src/admin.rl"
+#line 304 "src/admin.rl"
 	{start(out); fiber_info(out); end(out);}
 	goto st7;
 tr138:
-#line 299 "src/admin.rl"
+#line 303 "src/admin.rl"
 	{start(out); tarantool_info(out); end(out);}
 	goto st7;
 tr147:
-#line 218 "src/admin.rl"
+#line 222 "src/admin.rl"
 	{
 			start(out);
 			errinj_info(out);
@@ -518,22 +522,22 @@ case 135:
 		}
 	goto st7;
 tr153:
-#line 303 "src/admin.rl"
+#line 307 "src/admin.rl"
 	{start(out); palloc_stat(out); end(out);}
 	goto st7;
 tr161:
-#line 302 "src/admin.rl"
+#line 306 "src/admin.rl"
 	{start(out); show_slab(out); end(out);}
 	goto st7;
 tr165:
-#line 304 "src/admin.rl"
+#line 308 "src/admin.rl"
 	{start(out); show_stat(out);end(out);}
 	goto st7;
 st7:
 	if ( ++p == pe )
 		goto _test_eof7;
 case 7:
-#line 537 "src/admin.m"
+#line 541 "src/admin.cc"
 	if ( (*p) == 10 )
 		goto st135;
 	goto st0;
@@ -686,28 +690,28 @@ case 23:
 	}
 	goto tr33;
 tr33:
-#line 283 "src/admin.rl"
+#line 287 "src/admin.rl"
 	{strstart = p;}
 	goto st24;
 st24:
 	if ( ++p == pe )
 		goto _test_eof24;
 case 24:
-#line 697 "src/admin.m"
+#line 701 "src/admin.cc"
 	switch( (*p) ) {
 		case 10: goto tr36;
 		case 13: goto tr37;
 	}
 	goto st24;
 tr34:
-#line 283 "src/admin.rl"
+#line 287 "src/admin.rl"
 	{strstart = p;}
 	goto st25;
 st25:
 	if ( ++p == pe )
 		goto _test_eof25;
 case 25:
-#line 711 "src/admin.m"
+#line 715 "src/admin.cc"
 	switch( (*p) ) {
 		case 10: goto tr36;
 		case 13: goto tr37;
@@ -1157,28 +1161,28 @@ case 73:
 		goto tr91;
 	goto st0;
 tr91:
-#line 291 "src/admin.rl"
+#line 295 "src/admin.rl"
 	{ strstart = p; }
 	goto st74;
 st74:
 	if ( ++p == pe )
 		goto _test_eof74;
 case 74:
-#line 1168 "src/admin.m"
+#line 1172 "src/admin.cc"
 	if ( (*p) == 32 )
 		goto tr92;
 	if ( 33 <= (*p) && (*p) <= 126 )
 		goto st74;
 	goto st0;
 tr92:
-#line 291 "src/admin.rl"
+#line 295 "src/admin.rl"
 	{ strend = p; }
 	goto st75;
 st75:
 	if ( ++p == pe )
 		goto _test_eof75;
 case 75:
-#line 1182 "src/admin.m"
+#line 1186 "src/admin.cc"
 	switch( (*p) ) {
 		case 32: goto st75;
 		case 111: goto st76;
@@ -1870,7 +1874,7 @@ case 134:
 	_out: {}
 	}
 
-#line 315 "src/admin.rl"
+#line 319 "src/admin.rl"
 
 
 	in->pos = pe;
@@ -1892,25 +1896,26 @@ admin_handler(va_list ap)
 	struct iobuf *iobuf = va_arg(ap, struct iobuf *);
 	lua_State *L = lua_newthread(tarantool_L);
 	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
-	@try {
-		/*
-		 * Admin and iproto connections must have a
-		 * session object, representing the state of
-		 * a remote client: it's used in Lua
-		 * stored procedures.
-		 */
-		session_create(coio.fd);
-		for (;;) {
-			if (admin_dispatch(&coio, iobuf, L) < 0)
-				return;
-			iobuf_gc(iobuf);
-			fiber_gc();
-		}
-	} @finally {
+
+	auto scoped_guard = make_scoped_guard([&] {
 		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
 		evio_close(&coio);
 		iobuf_delete(iobuf);
 		session_destroy(fiber->sid);
+	});
+
+	/*
+	 * Admin and iproto connections must have a
+	 * session object, representing the state of
+	 * a remote client: it's used in Lua
+	 * stored procedures.
+	 */
+	session_create(coio.fd);
+	for (;;) {
+		if (admin_dispatch(&coio, iobuf, L) < 0)
+			return;
+		iobuf_gc(iobuf);
+		fiber_gc();
 	}
 }
 
diff --git a/src/admin.rl b/src/admin.rl
index 5172efcfb6a69dc8a05ac6256c5441add27e9a23..4cccfb31b3ac2220603e85e9328c92f16f038bd6 100644
--- a/src/admin.rl
+++ b/src/admin.rl
@@ -45,11 +45,15 @@
 #include <errinj.h>
 #include "coio_buf.h"
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+
 #include "box/box.h"
 #include "session.h"
+#include "scoped_guard.h"
 
 static const char *help =
 	"available commands:" CRLF
@@ -83,7 +87,7 @@ struct salloc_stat_admin_cb_ctx {
 static int
 salloc_stat_admin_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
 {
-	struct salloc_stat_admin_cb_ctx *ctx = cb_ctx;
+	struct salloc_stat_admin_cb_ctx *ctx = (struct salloc_stat_admin_cb_ctx *) cb_ctx;
 
 	tbuf_printf(ctx->out,
 		    "     - { item_size: %- 5i, slabs: %- 3i, items: %- 11" PRIi64
@@ -159,7 +163,7 @@ tarantool_info(struct tbuf *out)
 	tbuf_printf(out, "  lsn: %" PRIi64 CRLF,
 		    recovery_state->confirmed_lsn);
 	tbuf_printf(out, "  recovery_lag: %.3f" CRLF,
-		    recovery_state->remote ? 
+		    recovery_state->remote ?
 		    recovery_state->remote->recovery_lag : 0);
 	tbuf_printf(out, "  recovery_last_update: %.3f" CRLF,
 		    recovery_state->remote ?
@@ -174,7 +178,7 @@ tarantool_info(struct tbuf *out)
 static int
 show_stat_item(const char *name, int rps, i64 total, void *ctx)
 {
-	struct tbuf *buf = ctx;
+	struct tbuf *buf = (struct tbuf *) ctx;
 	int name_len = strlen(name);
 	tbuf_printf(buf,
 		    "  %s:%*s{ rps: %- 6i, total: %- 12" PRIi64 " }" CRLF,
@@ -200,7 +204,7 @@ admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
 	char *strstart, *strend;
 	bool state;
 
-	while ((pe = memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
+	while ((pe = (char *) memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
 		if (coio_bread(coio, in, 1) <= 0)
 			return -1;
 	}
@@ -309,7 +313,7 @@ admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
 			    check " "+ slab		%{slab_validate(); ok(out);}			|
 			    reload " "+ configuration	%reload_configuration);
 
-	        main := commands eol;
+		main := commands eol;
 		write init;
 		write exec;
 	}%%
@@ -333,25 +337,26 @@ admin_handler(va_list ap)
 	struct iobuf *iobuf = va_arg(ap, struct iobuf *);
 	lua_State *L = lua_newthread(tarantool_L);
 	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
-	@try {
-		/*
-		 * Admin and iproto connections must have a
-		 * session object, representing the state of
-		 * a remote client: it's used in Lua
-		 * stored procedures.
-		 */
-		session_create(coio.fd);
-		for (;;) {
-			if (admin_dispatch(&coio, iobuf, L) < 0)
-				return;
-			iobuf_gc(iobuf);
-			fiber_gc();
-		}
-	} @finally {
+
+	auto scoped_guard = make_scoped_guard([&] {
 		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
 		evio_close(&coio);
 		iobuf_delete(iobuf);
 		session_destroy(fiber->sid);
+	});
+
+	/*
+	 * Admin and iproto connections must have a
+	 * session object, representing the state of
+	 * a remote client: it's used in Lua
+	 * stored procedures.
+	 */
+	session_create(coio.fd);
+	for (;;) {
+		if (admin_dispatch(&coio, iobuf, L) < 0)
+			return;
+		iobuf_gc(iobuf);
+		fiber_gc();
 	}
 }
 
diff --git a/src/assoc.m b/src/assoc.cc
similarity index 100%
rename from src/assoc.m
rename to src/assoc.cc
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index a01ab0354125f4a9e7ed31c58a046cd98adf76d9..bed63be8447d271d5dcbd0a175dbadc99d4cee58 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -28,8 +28,8 @@ add_custom_target(generate_lua_sources}
     DEPENDS ${lua_sources})
 set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources})
 
-tarantool_module("box" tuple.m index.m hash_index.m tree_index.m space.m
-    port.m request.m txn.m box.m ${lua_sources} box_lua.m box_lua_space.m
-    bitset_index.m)
+tarantool_module("box" tuple.cc index.cc hash_index.cc tree_index.cc space.cc
+    port.cc request.cc txn.cc box.cc ${lua_sources} box_lua.cc box_lua_space.cc
+    bitset_index.cc)
 
 target_link_libraries(tarantool_box bitset)
diff --git a/src/box/bitset_index.m b/src/box/bitset_index.cc
similarity index 67%
rename from src/box/bitset_index.m
rename to src/box/bitset_index.cc
index b4ee44723469599d3600a4cc5ca14d81d3b920ae..82e9ecedcef29932aaf88f1a271d8e95afb046d6 100644
--- a/src/box/bitset_index.m
+++ b/src/box/bitset_index.cc
@@ -39,7 +39,7 @@
 #include <lib/bitset/index.h>
 
 static struct index_traits bitset_index_traits = {
-	.allows_partial_key = false,
+	/* .allows_partial_key = */ false,
 };
 
 static inline size_t
@@ -53,7 +53,7 @@ tuple_to_value(struct tuple *tuple)
 static inline struct tuple *
 value_to_tuple(size_t value)
 {
-	return salloc_ptr_from_index(value);
+	return (struct tuple *) salloc_ptr_from_index(value);
 }
 
 struct bitset_index_iterator {
@@ -90,86 +90,85 @@ bitset_index_iterator_next(struct iterator *iterator)
 	return value_to_tuple(value);
 }
 
-@implementation BitsetIndex;
-
-+ (struct index_traits *) traits
+BitsetIndex::BitsetIndex(struct key_def *key_def, struct space *space)
+	: Index(key_def, space)
 {
-	return &bitset_index_traits;
-}
-
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
-{
-	assert (!key_def_arg->is_unique);
-
-	self = [super init: key_def_arg :space_arg];
-	assert (self != NULL);
+	assert (!key_def->is_unique);
 
-	if (bitset_index_create(&self->index, realloc) != 0)
+	if (bitset_index_create(&index, realloc) != 0)
 		panic_syserror("bitset_index_create");
-
-	return self;
 }
 
-- (void) free
+BitsetIndex::~BitsetIndex()
 {
-	bitset_index_destroy(&self->index);
-	[super free];
+	bitset_index_destroy(&index);
 }
 
-- (void) beginBuild
+void
+BitsetIndex::beginBuild()
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "beginBuild()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "beginBuild()");
 }
 
-- (void) buildNext: (struct tuple *)tuple
+void
+BitsetIndex::buildNext(struct tuple *tuple)
 {
 	(void) tuple;
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "buildNext()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "buildNext()");
 }
 
-- (void) endBuild
+void
+BitsetIndex::endBuild()
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "endBuild()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "endBuild()");
 }
 
-- (void) build: (Index *) pk
+void
+BitsetIndex::build(Index *pk)
 {
 	assert (!key_def->is_unique);
 
-	struct iterator *it = pk->position;
+	struct iterator *it = pk->primaryIterator();
 	struct tuple *tuple;
-	[pk initIterator: it :ITER_ALL :NULL :0];
+	pk->initIterator(it, ITER_ALL, NULL, 0);
 
 	while ((tuple = it->next(it)))
-		[self replace: NULL :tuple :DUP_INSERT];
+		replace(NULL, tuple, DUP_INSERT);
 }
 
-- (size_t) size
+size_t
+BitsetIndex::size() const
 {
-	return bitset_index_size(&self->index);
+	return bitset_index_size(&index);
 }
 
-- (struct tuple *) min
+struct tuple *
+BitsetIndex::min() const
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "min()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "min()");
 	return NULL;
 }
 
-- (struct tuple *) max
+struct tuple *
+BitsetIndex::max() const
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "max()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "max()");
 	return NULL;
 }
 
-- (struct tuple *) random
+struct tuple *
+BitsetIndex::random(u32 rnd) const
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "random()");
+	(void) rnd;
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "random()");
 	return NULL;
 }
 
-- (struct iterator *) allocIterator
+struct iterator *
+BitsetIndex::allocIterator() const
 {
-	struct bitset_index_iterator *it = malloc(sizeof(*it));
+	struct bitset_index_iterator *it = (struct bitset_index_iterator *)
+			malloc(sizeof(*it));
 	if (!it)
 		return NULL;
 
@@ -182,38 +181,40 @@ bitset_index_iterator_next(struct iterator *iterator)
 	return (struct iterator *) it;
 }
 
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count
+struct tuple *
+BitsetIndex::findByKey(const void *key, u32 part_count) const
 {
 	(void) key;
 	(void) part_count;
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "findByKey()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "findByKey()");
 	return NULL;
 }
 
-- (struct tuple *) findByTuple: (struct tuple *) tuple
+struct tuple *
+BitsetIndex::findByTuple(struct tuple *tuple) const
 {
 	(void) tuple;
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "BitsetIndex", "findByTuple()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "BitsetIndex", "findByTuple()");
 	return NULL;
 }
 
-- (struct tuple *) replace: (struct tuple *) old_tuple
-	: (struct tuple *) new_tuple
-	: (enum dup_replace_mode) flags
+struct tuple *
+BitsetIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		     enum dup_replace_mode mode)
 {
 	assert(!key_def->is_unique);
 	assert(old_tuple != NULL || new_tuple != NULL);
-	(void) flags;
+	(void) mode;
 
 	struct tuple *ret = NULL;
 
 	if (old_tuple != NULL) {
 		size_t value = tuple_to_value(old_tuple);
-		if (bitset_index_contains_value(&self->index, value)) {
+		if (bitset_index_contains_value(&index, value)) {
 			ret = old_tuple;
 
 			assert (old_tuple != new_tuple);
-			bitset_index_remove_value(&self->index, value);
+			bitset_index_remove_value(&index, value);
 		}
 	}
 
@@ -225,9 +226,9 @@ bitset_index_iterator_next(struct iterator *iterator)
 		const void *bitset_key = field;
 
 		size_t value = tuple_to_value(new_tuple);
-		if (bitset_index_insert(&self->index, bitset_key,
+		if (bitset_index_insert(&index, bitset_key,
 					bitset_key_size, value) < 0) {
-			tnt_raise(ClientError, :ER_MEMORY_ISSUE, 0,
+			tnt_raise(ClientError, ER_MEMORY_ISSUE, 0,
 				  "BitsetIndex", "insert");
 		}
 	}
@@ -235,8 +236,9 @@ bitset_index_iterator_next(struct iterator *iterator)
 	return ret;
 }
 
-- (void) initIterator: (struct iterator *) iterator:(enum iterator_type) type
-      :(const void *) key :(u32) part_count
+void
+BitsetIndex::initIterator(struct iterator *iterator, enum iterator_type type,
+			  const void *key, u32 part_count) const
 {
 	assert(iterator->free == bitset_index_iterator_free);
 	struct bitset_index_iterator *it = bitset_index_iterator(iterator);
@@ -254,7 +256,7 @@ bitset_index_iterator_next(struct iterator *iterator)
 
 	struct bitset_expr expr;
 	bitset_expr_create(&expr, realloc);
-	@try {
+	try {
 		int rc = 0;
 		switch (type) {
 		case ITER_ALL:
@@ -277,23 +279,27 @@ bitset_index_iterator_next(struct iterator *iterator)
 						       bitset_key_size);
 			break;
 		default:
-			tnt_raise(ClientError, :ER_UNSUPPORTED,
+			tnt_raise(ClientError, ER_UNSUPPORTED,
 				  "BitsetIndex", "requested iterator type");
 		}
 
 		if (rc != 0) {
-			tnt_raise(ClientError, :ER_MEMORY_ISSUE,
+			tnt_raise(ClientError, ER_MEMORY_ISSUE,
 				  0, "BitsetIndex", "iterator expression");
 		}
 
-		if (bitset_index_init_iterator(&self->index, &it->bitset_it,
+		/* TODO: fix bitset_index_init_iterator to work with const obj*/
+		if (bitset_index_init_iterator((bitset_index *) &index,
+					       &it->bitset_it,
 					       &expr) != 0) {
-			tnt_raise(ClientError, :ER_MEMORY_ISSUE,
+			tnt_raise(ClientError, ER_MEMORY_ISSUE,
 				  0, "BitsetIndex", "iterator state");
 		}
-	} @finally {
+
+		bitset_expr_destroy(&expr);
+	} catch(const Exception& e) {
 		bitset_expr_destroy(&expr);
+		throw;
 	}
 }
 
-@end
diff --git a/src/box/bitset_index.h b/src/box/bitset_index.h
index fbaf074409b3253a72dc96a24f02078591f2f5f8..b36909ce7bcffb3082c3b065f47ee06375e5e3b1 100644
--- a/src/box/bitset_index.h
+++ b/src/box/bitset_index.h
@@ -41,10 +41,31 @@
 struct bitset_index;
 struct bitset_expr;
 
-@interface BitsetIndex: Index {
-	@private
+class BitsetIndex: public Index {
+public:
+	BitsetIndex(struct key_def *key_def, struct space *space);
+	virtual ~BitsetIndex();
+
+	virtual void beginBuild();
+	virtual void buildNext(struct tuple *tuple);
+	virtual void endBuild();
+	virtual void build(Index *pk);
+	virtual size_t size() const;
+	virtual struct tuple *min() const;
+	virtual struct tuple *max() const;
+	virtual struct tuple *random(u32 rnd) const;
+	virtual struct tuple *findByKey(const void *key, u32 part_count) const;
+	virtual struct tuple *findByTuple(struct tuple *tuple) const;
+	virtual struct tuple *replace(struct tuple *old_tuple,
+				      struct tuple *new_tuple,
+				      enum dup_replace_mode mode);
+
+	virtual struct iterator *allocIterator() const;
+	virtual void initIterator(struct iterator *iterator,
+				  enum iterator_type type,
+				  const void *key, u32 part_count) const;
+private:
 	struct bitset_index index;
-}
-@end
+};
 
 #endif /* TARANTOOL_BOX_INDEX_BITSET_H_INCLUDED */
diff --git a/src/box/box.m b/src/box/box.cc
similarity index 87%
rename from src/box/box.m
rename to src/box/box.cc
index b4e5ed11740c65f596c35617053fe4f3bab1d529..1e46786a1d996de6d71597f5d7f9d016d5397795 100644
--- a/src/box/box.m
+++ b/src/box/box.cc
@@ -29,7 +29,11 @@
 #include "box/box.h"
 #include <arpa/inet.h>
 
+extern "C" {
 #include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
+
 #include <errcode.h>
 #include "palloc.h"
 #include <recovery.h>
@@ -38,8 +42,6 @@
 #include <say.h>
 #include <stat.h>
 #include <tarantool.h>
-
-#include <cfg/tarantool_box_cfg.h>
 #include "tuple.h"
 #include "memcached.h"
 #include "box_lua.h"
@@ -81,7 +83,7 @@ process_rw(struct port *port, u32 op, const void *reqdata, u32 reqlen)
 {
 	struct txn *txn = txn_begin();
 
-	@try {
+	try {
 		struct request *request = request_create(op, reqdata, reqlen);
 		stat_collect(stat_base, op, 1);
 		request_execute(request, txn, port);
@@ -89,9 +91,9 @@ process_rw(struct port *port, u32 op, const void *reqdata, u32 reqlen)
 		port_send_tuple(port, txn, request->flags);
 		port_eof(port);
 		txn_finish(txn);
-	} @catch (id e) {
+	} catch (const Exception& e) {
 		txn_rollback(txn);
-		@throw;
+		throw;
 	}
 }
 
@@ -99,7 +101,7 @@ static void
 process_replica(struct port *port, u32 op, const void *reqdata, u32 reqlen)
 {
 	if (!request_is_select(op)) {
-		tnt_raise(ClientError, :ER_NONMASTER,
+		tnt_raise(ClientError, ER_NONMASTER,
 			  cfg.replication_source);
 	}
 	return process_rw(port, op, reqdata, reqlen);
@@ -109,7 +111,7 @@ static void
 process_ro(struct port *port, u32 op, const void *reqdata, u32 reqlen)
 {
 	if (!request_is_select(op))
-		tnt_raise(LoggedError, :ER_SECONDARY);
+		tnt_raise(LoggedError, ER_SECONDARY);
 	return process_rw(port, op, reqdata, reqlen);
 }
 
@@ -118,7 +120,7 @@ recover_snap_row(const void *data)
 {
 	assert(primary_indexes_enabled == false);
 
-	const struct box_snap_row *row = data;
+	const struct box_snap_row *row = (const struct box_snap_row *) data;
 
 	struct tuple *tuple = tuple_alloc(row->data_size);
 	memcpy(tuple->data, row->data, row->data_size);
@@ -128,9 +130,9 @@ recover_snap_row(const void *data)
 	Index *index = space_index(space, 0);
 	/* Check to see if the tuple has a sufficient number of fields. */
 	if (unlikely(tuple->field_count < space->max_fieldno)) {
-		tnt_raise(IllegalParams, :"tuple must have all indexed fields");
+		tnt_raise(IllegalParams, "tuple must have all indexed fields");
 	}
-	[index buildNext: tuple];
+	index->buildNext(tuple);
 	tuple_ref(tuple, 1);
 }
 
@@ -144,7 +146,7 @@ recover_row(void *param __attribute__((unused)), struct tbuf *t)
 		return -1;
 	}
 
-	@try {
+	try {
 		const void *data = t->data;
 		const void *end = t->data + t->size;
 		u16 tag = pick_u16(&data, end);
@@ -153,15 +155,14 @@ recover_row(void *param __attribute__((unused)), struct tbuf *t)
 			recover_snap_row(data);
 		} else if (tag == XLOG) {
 			u16 op = pick_u16(&data, end);
-			process_rw(&port_null, op, data, end - data);
+			process_rw(&port_null, op, data,
+				   (const char *) end - (const char *) data);
 		} else {
 			say_error("unknown row tag: %i", (int)tag);
 			return -1;
 		}
-	} @catch (tnt_Exception *e) {
-		[e log];
-		return -1;
-	} @catch (id e) {
+	} catch (const Exception& e) {
+		e.log();
 		return -1;
 	}
 
@@ -210,7 +211,7 @@ box_check_config(struct tarantool_cfg *conf)
 {
 	/* replication & hot standby modes can not work together */
 	if (conf->replication_source != NULL && conf->local_hot_standby > 0) {
-		out_warning(0, "replication and local hot standby modes "
+		out_warning(CNF_OK, "replication and local hot standby modes "
 			       "can't be enabled simultaneously");
 		return -1;
 	}
@@ -223,11 +224,11 @@ box_check_config(struct tarantool_cfg *conf)
 
 		if (sscanf(conf->replication_source, "%31[^:]:%i",
 			   ip_addr, &port) != 2) {
-			out_warning(0, "replication source IP address is not recognized");
+			out_warning(CNF_OK, "replication source IP address is not recognized");
 			return -1;
 		}
 		if (port <= 0 || port >= USHRT_MAX) {
-			out_warning(0, "invalid replication source port value: %i", port);
+			out_warning(CNF_OK, "invalid replication source port value: %i", port);
 			return -1;
 		}
 	}
@@ -235,20 +236,20 @@ box_check_config(struct tarantool_cfg *conf)
 	/* check primary port */
 	if (conf->primary_port != 0 &&
 	    (conf->primary_port <= 0 || conf->primary_port >= USHRT_MAX)) {
-		out_warning(0, "invalid primary port value: %i", conf->primary_port);
+		out_warning(CNF_OK, "invalid primary port value: %i", conf->primary_port);
 		return -1;
 	}
 
 	/* check secondary port */
 	if (conf->secondary_port != 0 &&
 	    (conf->secondary_port <= 0 || conf->secondary_port >= USHRT_MAX)) {
-		out_warning(0, "invalid secondary port value: %i", conf->primary_port);
+		out_warning(CNF_OK, "invalid secondary port value: %i", conf->primary_port);
 		return -1;
 	}
 
 	/* check if at least one space is defined */
 	if (conf->space == NULL && conf->memcached_port == 0) {
-		out_warning(0, "at least one space or memcached port must be defined");
+		out_warning(CNF_OK, "at least one space or memcached port must be defined");
 		return -1;
 	}
 
@@ -276,7 +277,7 @@ box_reload_config(struct tarantool_cfg *old_conf, struct tarantool_cfg *new_conf
 	     (strcmp(old_conf->replication_source, new_conf->replication_source) != 0))) {
 
 		if (recovery_state->finalize != true) {
-			out_warning(0, "Could not propagate %s before local recovery finished",
+			out_warning(CNF_OK, "Could not propagate %s before local recovery finished",
 				    old_is_replica == true ? "slave to master" :
 				    "master to slave");
 
@@ -358,14 +359,19 @@ snapshot_write_tuple(struct log_io *l, struct fio_batch *batch,
 }
 
 
+struct snapshot_space_param {
+	struct log_io *l;
+	struct fio_batch *batch;
+};
+
 static void
 snapshot_space(struct space *sp, void *udata)
 {
 	struct tuple *tuple;
-	struct { struct log_io *l; struct fio_batch *batch; } *ud = udata;
+	struct snapshot_space_param *ud = (struct snapshot_space_param *) udata;
 	Index *pk = space_index(sp, 0);
-	struct iterator *it = pk->position;
-	[pk initIterator: it :ITER_ALL :NULL :0];
+	struct iterator *it = pk->primaryIterator();;
+	pk->initIterator(it, ITER_ALL, NULL, 0);
 
 	while ((tuple = it->next(it)))
 		snapshot_write_tuple(ud->l, ud->batch, space_n(sp), tuple);
@@ -378,7 +384,7 @@ box_snapshot(struct log_io *l, struct fio_batch *batch)
 	if (primary_indexes_enabled == false)
 		return;
 
-	struct { struct log_io *l; struct fio_batch *batch; } ud = { l, batch };
+	struct snapshot_space_param ud = { l, batch };
 
 	space_foreach(snapshot_space, &ud);
 }
diff --git a/src/box/box_lua.m b/src/box/box_lua.cc
similarity index 91%
rename from src/box/box_lua.m
rename to src/box/box_lua.cc
index f62d946a7a2d8d48a2c14280f87d9ba0676e0140..9c5a286e9405f0e2b02680cd8b3b81732d45ce9b 100644
--- a/src/box/box_lua.m
+++ b/src/box/box_lua.cc
@@ -33,19 +33,22 @@
 #include "request.h"
 #include "txn.h"
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-#include "lj_obj.h"
-#include "lj_ctype.h"
-#include "lj_cdata.h"
-#include "lj_cconv.h"
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include <lj_obj.h>
+#include <lj_ctype.h>
+#include <lj_cdata.h>
+#include <lj_cconv.h>
+} /* extern "C" */
 
 #include "pickle.h"
 #include "tuple.h"
 #include "space.h"
 #include "port.h"
 #include "tbuf.h"
+#include "scoped_guard.h"
 
 /* contents of box.lua, misc.lua, box.net.lua respectively */
 extern char box_lua[], box_net_lua[], misc_lua[];
@@ -87,7 +90,7 @@ lua_totuple(struct lua_State *L, int index);
 static inline struct tuple *
 lua_checktuple(struct lua_State *L, int narg)
 {
-	struct tuple *t = *(void **) luaL_checkudata(L, narg, tuplelib_name);
+	struct tuple *t = *(struct tuple **) luaL_checkudata(L, narg, tuplelib_name);
 	assert(t->refs);
 	return t;
 }
@@ -100,7 +103,7 @@ lua_istuple(struct lua_State *L, int narg)
 	luaL_getmetatable(L, tuplelib_name);
 	struct tuple *tuple = 0;
 	if (lua_equal(L, -1, -2))
-		tuple = * (void **) lua_touserdata(L, narg);
+		tuple = *(struct tuple **) lua_touserdata(L, narg);
 	lua_pop(L, 2);
 	return tuple;
 }
@@ -161,12 +164,12 @@ lbox_tuple_slice(struct lua_State *L)
 	if (end <= start)
 		luaL_error(L, "tuple.slice(): start must be less than end");
 
-	const void *field = tuple->data;
+	const char *field = (const char *) tuple->data;
 	u32 fieldno = 0;
 	u32 stop = end - 1;
 
-	while (field < (const void *) tuple->data + tuple->bsize) {
-		size_t len = load_varint32(&field);
+	while (field < (const char *) tuple->data + tuple->bsize) {
+		size_t len = load_varint32((const void **) &field);
 		if (fieldno >= start) {
 			lua_pushlstring(L, field, len);
 			if (fieldno == stop)
@@ -230,7 +233,7 @@ transform_calculate(struct lua_State *L, struct tuple *tuple,
 	tuple_range_size(&tuple_field, tuple_end, len);
 
 	/* calculate last part of the tuple fields */
-	lr[1] = tuple_end - tuple_field;
+	lr[1] = (const char *) tuple_end - (const char *) tuple_field;
 
 	return lr[0] + mid + lr[1];
 }
@@ -327,9 +330,9 @@ tuple_find(struct lua_State *L, struct tuple *tuple, size_t offset,
 	int idx = offset;
 	if (idx >= tuple->field_count)
 		return 0;
-	const void *field = tuple_field(tuple, idx);
-	while (field < (const void *) tuple->data + tuple->bsize) {
-		size_t len = load_varint32(&field);
+	const char *field = (const char *) tuple_field(tuple, idx);
+	while (field < (const char *) tuple->data + tuple->bsize) {
+		size_t len = load_varint32((const void **) &field);
 		if (len == key_size && (memcmp(field, key, len) == 0)) {
 			lua_pushinteger(L, idx);
 			if (!all)
@@ -397,10 +400,10 @@ lbox_tuple_unpack(struct lua_State *L)
 	struct tuple *tuple = lua_checktuple(L, 1);
 	const void *field = tuple->data;
 
-	while (field < (const void *) tuple->data + tuple->bsize) {
+	while (field < (const char *) tuple->data + tuple->bsize) {
 		size_t len = load_varint32(&field);
-		lua_pushlstring(L, field, len);
-		field += len;
+		lua_pushlstring(L, (const char *) field, len);
+		field = (const char *) field + len;
 	}
 	assert(lua_gettop(L) == tuple->field_count + 1);
 	return tuple->field_count;
@@ -413,12 +416,12 @@ lbox_tuple_totable(struct lua_State *L)
 	lua_newtable(L);
 	int index = 1;
 	const void *field = tuple->data;
-	while (field < (const void *) tuple->data + tuple->bsize) {
+	while (field < (const char *) tuple->data + tuple->bsize) {
 		size_t len = load_varint32(&field);
 		lua_pushnumber(L, index++);
-		lua_pushlstring(L, field, len);
+		lua_pushlstring(L, (const char *) field, len);
 		lua_rawset(L, -3);
-		field += len;
+		field = (const char *) field + len;
 	}
 	return 1;
 }
@@ -442,7 +445,7 @@ lbox_tuple_index(struct lua_State *L)
 				   tuplelib_name, i, tuple->field_count-1);
 		const void *field = tuple_field(tuple, i);
 		u32 len = load_varint32(&field);
-		lua_pushlstring(L, field, len);
+		lua_pushlstring(L, (const char *) field, len);
 		return 1;
 	}
 	/* If we got a string, try to find a method for it. */
@@ -467,7 +470,8 @@ static void
 lbox_pushtuple(struct lua_State *L, struct tuple *tuple)
 {
 	if (tuple) {
-		void **ptr = lua_newuserdata(L, sizeof(void *));
+		struct tuple **ptr = (struct tuple **)
+				lua_newuserdata(L, sizeof(void *));
 		luaL_getmetatable(L, tuplelib_name);
 		lua_setmetatable(L, -2);
 		*ptr = tuple;
@@ -499,10 +503,10 @@ lbox_tuple_next(struct lua_State *L)
 
 	(void)field;
 	assert(field >= (const void *) tuple->data);
-	if (field < (const void *) tuple->data + tuple->bsize) {
+	if (field < (const char *) tuple->data + tuple->bsize) {
 		len = load_varint32(&field);
-		lua_pushlightuserdata(L, (void *) field + len);
-		lua_pushlstring(L, field, len);
+		lua_pushlightuserdata(L, (char *) field + len);
+		lua_pushlstring(L, (char *) field, len);
 		return 2;
 	}
 	lua_pushnil(L);
@@ -566,28 +570,33 @@ static const char *iteratorlib_name = "box.index.iterator";
 static struct iterator *
 lbox_checkiterator(struct lua_State *L, int i)
 {
-	struct iterator **it = luaL_checkudata(L, i, iteratorlib_name);
+	struct iterator **it = (struct iterator **)
+			luaL_checkudata(L, i, iteratorlib_name);
 	assert(it != NULL);
 	return *it;
 }
 
+
+
 static void
 lbox_pushiterator(struct lua_State *L, Index *index,
-                  struct iterator *it, enum iterator_type type,
-                  const void *key, size_t size, int part_count)
+		  struct iterator *it, enum iterator_type type,
+		  const void *key, size_t size, int part_count)
 {
-	struct {
+	struct lbox_iterator_holder {
 		struct iterator *it;
 		char key[];
-	} *holder = lua_newuserdata(L, sizeof(void *) + size);
+	};
+
+	struct lbox_iterator_holder *holder = (struct lbox_iterator_holder *)
+			lua_newuserdata(L, sizeof(void *) + size);
 	luaL_getmetatable(L, iteratorlib_name);
 	lua_setmetatable(L, -2);
 
 	holder->it = it;
 	memcpy(holder->key, key, size);
 
-	[index initIterator: it :type :(key ? holder->key : NULL)
-		:part_count];
+	index->initIterator(it, type, (key ? holder->key : NULL), part_count);
 }
 
 static int
@@ -601,7 +610,7 @@ lbox_iterator_gc(struct lua_State *L)
 static Index *
 lua_checkindex(struct lua_State *L, int i)
 {
-	Index **index = luaL_checkudata(L, i, indexlib_name);
+	Index **index = (Index **) luaL_checkudata(L, i, indexlib_name);
 	assert(index != NULL);
 	return *index;
 }
@@ -616,7 +625,7 @@ lbox_index_new(struct lua_State *L)
 	Index *index = index_find(sp, idx);
 
 	/* create a userdata object */
-	void **ptr = lua_newuserdata(L, sizeof(void *));
+	void **ptr = (void **) lua_newuserdata(L, sizeof(void *));
 	*ptr = index;
 	/* set userdata object metatable to indexlib */
 	luaL_getmetatable(L, indexlib_name);
@@ -638,7 +647,7 @@ static int
 lbox_index_len(struct lua_State *L)
 {
 	Index *index = lua_checkindex(L, 1);
-	lua_pushinteger(L, [index size]);
+	lua_pushinteger(L, index->size());
 	return 1;
 }
 
@@ -654,7 +663,7 @@ static int
 lbox_index_min(struct lua_State *L)
 {
 	Index *index = lua_checkindex(L, 1);
-	lbox_pushtuple(L, [index min]);
+	lbox_pushtuple(L, index->min());
 	return 1;
 }
 
@@ -662,7 +671,7 @@ static int
 lbox_index_max(struct lua_State *L)
 {
 	Index *index = lua_checkindex(L, 1);
-	lbox_pushtuple(L, [index max]);
+	lbox_pushtuple(L, index->max());
 	return 1;
 }
 
@@ -674,7 +683,7 @@ lbox_index_random(struct lua_State *L)
 
 	Index *index = lua_checkindex(L, 1);
 	u32 rnd = lua_tointeger(L, 2);
-	lbox_pushtuple(L, [index random: rnd]);
+	lbox_pushtuple(L, index->random(rnd));
 	return 1;
 }
 
@@ -718,8 +727,8 @@ void append_key_part(struct lua_State *L, int i,
 		str = luaL_checklstring(L, i, &size);
 	}
 	char varint_buf[sizeof(u32) + 1];
-	size_t pack_len = (pack_varint32(varint_buf, size) -
-			   (void *) varint_buf);
+	size_t pack_len = ((const char *) pack_varint32(varint_buf, size) -
+			   (const char *) varint_buf);
 	tbuf_append(tbuf, varint_buf, pack_len);
 	tbuf_append(tbuf, str, size);
 }
@@ -770,8 +779,8 @@ lbox_create_iterator(struct lua_State *L)
 		 * beginning (ITER_ALL).
 		 */
 	} else {
-		 type = luaL_checkint(L, 2);
-		 if (type >= iterator_type_MAX)
+		 type = (enum iterator_type) luaL_checkint(L, 2);
+		 if (type < ITER_ALL || type >= iterator_type_MAX)
 			 luaL_error(L, "unknown iterator type: %d", type);
 		 /* What else do we have on the stack? */
 		 if (argc == 2 || (argc == 3 && lua_type(L, 3) == LUA_TNIL)) {
@@ -806,9 +815,9 @@ lbox_create_iterator(struct lua_State *L)
 				   " is greater than index part count %d",
 				   field_count, index->key_def->part_count);
 	}
-	struct iterator *it = [index allocIterator];
+	struct iterator *it = index->allocIterator();
 	lbox_pushiterator(L, index, it, type, key, key_size,
-	                  field_count);
+			  field_count);
 
 	/* truncate memory used by key construction */
 	ptruncate(fiber->gc_pool, allocated_size);
@@ -914,8 +923,8 @@ lbox_index_count(struct lua_State *L)
 	}
 	u32 count = 0;
 	/* preparing index iterator */
-	struct iterator *it = index->position;
-	[index initIterator: it :ITER_EQ :key :key_part_count];
+	struct iterator *it = index->primaryIterator();
+	index->initIterator(it, ITER_EQ, key, key_part_count);
 	/* iterating over the index and counting tuples */
 	struct tuple *tuple;
 	while ((tuple = it->next(it)) != NULL)
@@ -979,10 +988,10 @@ port_lua_add_tuple(struct port *port, struct tuple *tuple,
 		   u32 flags __attribute__((unused)))
 {
 	lua_State *L = port_lua(port)->L;
-	@try {
+	try {
 		lbox_pushtuple(L, tuple);
-	} @catch (id allOthers) {
-		tnt_raise(ClientError, :ER_PROC_LUA, lua_tostring(L, -1));
+	} catch (...) {
+		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
 	}
 }
 
@@ -994,7 +1003,8 @@ struct port_vtab port_lua_vtab = {
 static struct port *
 port_lua_create(struct lua_State *L)
 {
-	struct port_lua *port = palloc(fiber->gc_pool, sizeof(struct port_lua));
+	struct port_lua *port = (struct port_lua *)
+			palloc(fiber->gc_pool, sizeof(struct port_lua));
 	port->vtab = &port_lua_vtab;
 	port->L = L;
 	return (struct port *) port;
@@ -1044,7 +1054,7 @@ lua_table_to_tuple(struct lua_State *L, int index)
 			break;
 		}
 		default:
-			tnt_raise(ClientError, :ER_PROC_RET,
+			tnt_raise(ClientError, ER_PROC_RET,
 				  lua_typename(L, lua_type(L, -1)));
 			break;
 		}
@@ -1161,7 +1171,7 @@ lua_totuple(struct lua_State *L, int index)
 		/*
 		 * LUA_TNONE, LUA_TTABLE, LUA_THREAD, LUA_TFUNCTION
 		 */
-		tnt_raise(ClientError, :ER_PROC_RET, lua_typename(L, type));
+		tnt_raise(ClientError, ER_PROC_RET, lua_typename(L, type));
 		break;
 	}
 	return tuple;
@@ -1171,11 +1181,16 @@ static void
 port_add_lua_ret(struct port *port, struct lua_State *L, int index)
 {
 	struct tuple *tuple = lua_totuple(L, index);
-	@try {
+	try {
 		port_add_tuple(port, tuple, BOX_RETURN_TUPLE);
-	} @finally {
+
 		if (tuple->refs == 0)
 			tuple_free(tuple);
+	} catch(...) {
+		if (tuple->refs == 0)
+			tuple_free(tuple);
+
+		throw;
 	}
 }
 
@@ -1261,14 +1276,17 @@ lbox_process(lua_State *L)
 
 	size_t allocated_size = palloc_allocated(fiber->gc_pool);
 	struct port *port_lua = port_lua_create(L);
-	@try {
+	try {
 		box_process(port_lua, op, req, sz);
-	} @finally {
+
 		/*
 		 * This only works as long as port_lua doesn't
 		 * use fiber->cleanup and fiber->gc_pool.
 		 */
 		ptruncate(fiber->gc_pool, allocated_size);
+	} catch(const Exception& e) {
+		ptruncate(fiber->gc_pool, allocated_size);
+		throw;
 	}
 	return lua_gettop(L) - top;
 }
@@ -1282,7 +1300,7 @@ lbox_raise(lua_State *L)
 	if (!code)
 		luaL_error(L, "box.raise(): unknown error code");
 	const char *str = lua_tostring(L, 2);
-	tnt_raise(ClientError, :code :str);
+	tnt_raise(ClientError, str, code);
 	return 0;
 }
 
@@ -1296,12 +1314,12 @@ box_lua_find(lua_State *L, const char *name, const char *name_end)
 	int index = LUA_GLOBALSINDEX;
 	const char *start = name, *end;
 
-	while ((end = memchr(start, '.', name_end - start))) {
+	while ((end = (const char *) memchr(start, '.', name_end - start))) {
 		lua_checkstack(L, 3);
 		lua_pushlstring(L, start, end - start);
 		lua_gettable(L, index);
 		if (! lua_istable(L, -1))
-			tnt_raise(ClientError, :ER_NO_SUCH_PROC,
+			tnt_raise(ClientError, ER_NO_SUCH_PROC,
 				  name_end - name, name);
 		start = end + 1; /* next piece of a.b.c */
 		index = lua_gettop(L); /* top of the stack */
@@ -1311,7 +1329,7 @@ box_lua_find(lua_State *L, const char *name, const char *name_end)
 	if (! lua_isfunction(L, -1)) {
 		/* lua_call or lua_gettable would raise a type error
 		 * for us, but our own message is more verbose. */
-		tnt_raise(ClientError, :ER_NO_SUCH_PROC,
+		tnt_raise(ClientError, ER_NO_SUCH_PROC,
 			  name_end - name, name);
 	}
 	/* setting stack that it would contain only
@@ -1348,36 +1366,40 @@ void
 box_lua_execute(struct request *request, struct port *port)
 {
 	const void **reqpos = &request->data;
-	const void *reqend = request->data + request->len;
+	const void *reqend = (const char *) request->data + request->len;
 	lua_State *L = lua_newthread(root_L);
 	int coro_ref = luaL_ref(root_L, LUA_REGISTRYINDEX);
 	/* Request flags: not used. */
 	(void) (pick_u32(reqpos, reqend));
-	@try {
+
+	try {
+		auto scoped_guard = make_scoped_guard([=] {
+			/*
+			 * Allow the used coro to be garbage collected.
+			 * @todo: cache and reuse it instead.
+			 */
+			luaL_unref(root_L, LUA_REGISTRYINDEX, coro_ref);
+		});
+
 		u32 field_len;
 		/* proc name */
 		const void *field = pick_field_str(reqpos, reqend, &field_len);
-		box_lua_find(L, field, field + field_len);
+		box_lua_find(L, (const char *) field,
+			     ((const char *) field + field_len));
 		/* Push the rest of args (a tuple). */
 		u32 nargs = pick_u32(reqpos, reqend);
 		luaL_checkstack(L, nargs, "call: out of stack");
 		for (int i = 0; i < nargs; i++) {
 			field = pick_field_str(reqpos, reqend, &field_len);
-			lua_pushlstring(L, field, field_len);
+			lua_pushlstring(L, (const char *) field, field_len);
 		}
 		lua_call(L, nargs, LUA_MULTRET);
 		/* Send results of the called procedure to the client. */
 		port_add_lua_multret(port, L);
-	} @catch (tnt_Exception *e) {
-		@throw;
-	} @catch (id allOthers) {
-		tnt_raise(ClientError, :ER_PROC_LUA, lua_tostring(L, -1));
-	} @finally {
-		/*
-		 * Allow the used coro to be garbage collected.
-		 * @todo: cache and reuse it instead.
-		 */
-		luaL_unref(root_L, LUA_REGISTRYINDEX, coro_ref);
+	} catch (const Exception& e) {
+		throw;
+	} catch (...) {
+		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
 	}
 }
 
@@ -1399,7 +1421,7 @@ static void
 luaL_addvarint32(luaL_Buffer *b, u32 value)
 {
 	char buf[sizeof(u32)+1];
-	char *bufend = pack_varint32(buf, value);
+	char *bufend = (char *) pack_varint32(buf, value);
 	luaL_addlstring(b, buf, bufend - buf);
 }
 
@@ -1706,9 +1728,9 @@ lbox_unpack(struct lua_State *L)
 	const char *f = format;
 
 	size_t str_size = 0;
-	const void *str =  luaL_checklstring(L, 2, &str_size);
-	const void *end = str + str_size;
-	const void *s = str;
+	const char *str =  luaL_checklstring(L, 2, &str_size);
+	const char *end = (const char *) str + str_size;
+	const char *s = str;
 
 	int save_stacksize = lua_gettop(L);
 
@@ -1748,7 +1770,7 @@ lbox_unpack(struct lua_State *L)
 			break;
 		case 'w':
 			/* pick_varint32 throws exception on error. */
-			u32buf = pick_varint32(&s, end);
+			u32buf = pick_varint32((const void **) &s, end);
 			lua_pushnumber(L, u32buf);
 			break;
 
@@ -1760,7 +1782,7 @@ lbox_unpack(struct lua_State *L)
 		case 'P':
 		case 'p':
 			/* pick_varint32 throws exception on error. */
-			u32buf = pick_varint32(&s, end);
+			u32buf = pick_varint32((const void **) &s, end);
 			CHECK_SIZE(s + u32buf - 1);
 			lua_pushlstring(L, (const char *) s, u32buf);
 			s += u32buf;
diff --git a/src/box/box_lua_space.m b/src/box/box_lua_space.cc
similarity index 93%
rename from src/box/box_lua_space.m
rename to src/box/box_lua_space.cc
index a86fef2bb90e16e739bd138b88e81b2911e3bdc0..e70722f8565cb4d4054f47de42ba0b967e185525 100644
--- a/src/box/box_lua_space.m
+++ b/src/box/box_lua_space.cc
@@ -27,10 +27,14 @@
  * SUCH DAMAGE.
  */
 #include "box_lua_space.h"
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
+
 #include "space.h"
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
 #include <say.h>
 
 /**
@@ -145,6 +149,12 @@ lbox_add_space(struct space *space, struct lua_State *L)
 	lua_settable(L, -3);
 }
 
+static void
+lbox_add_space_wrapper(struct space *space, void *param)
+{
+	lbox_add_space(space, (struct lua_State *) param);
+}
+
 /**
  * Make all spaces available in Lua via box.space
  * array.
@@ -155,7 +165,7 @@ box_lua_load_cfg(struct lua_State *L)
 	lua_getfield(L, LUA_GLOBALSINDEX, "box");
 	lua_pushstring(L, "space");
 	lua_newtable(L);
-	space_foreach((void *)lbox_add_space, L);	/* fill box.space */
+	space_foreach(lbox_add_space_wrapper, L);	/* fill box.space */
 	lua_settable(L, -3);
 	lua_pop(L, 1);
 	assert(lua_gettop(L) == 0);
diff --git a/src/box/hash_index.m b/src/box/hash_index.cc
similarity index 63%
rename from src/box/hash_index.m
rename to src/box/hash_index.cc
index 17ef9bcb3209782e5205c1a1c8cc5533f032db0e..159e25fd64138fe960ab3ae743e8db337c52ac57 100644
--- a/src/box/hash_index.m
+++ b/src/box/hash_index.cc
@@ -36,7 +36,7 @@
 #include "errinj.h"
 
 static struct index_traits hash_index_traits = {
-	.allows_partial_key = false,
+	/* .allows_partial_key = */ false,
 };
 
 /* {{{ HashIndex Iterators ****************************************/
@@ -74,7 +74,7 @@ hash_iterator_i32_ge(struct iterator *ptr)
 
 	while (it->h_pos < mh_end(it->hash)) {
 		if (mh_exist(it->hash, it->h_pos))
-			return mh_i32ptr_node(it->hash, it->h_pos++)->val;
+			return (struct tuple *) mh_i32ptr_node(it->hash, it->h_pos++)->val;
 		it->h_pos++;
 	}
 	return NULL;
@@ -88,7 +88,8 @@ hash_iterator_i64_ge(struct iterator *ptr)
 
 	while (it->h_pos < mh_end(it->hash)) {
 		if (mh_exist(it->hash, it->h_pos))
-			return mh_i64ptr_node(it->hash, it->h_pos++)->val;
+			return (struct tuple *) mh_i64ptr_node(
+						it->hash,it->h_pos++)->val;
 		it->h_pos++;
 	}
 	return NULL;
@@ -102,7 +103,8 @@ hash_iterator_lstr_ge(struct iterator *ptr)
 
 	while (it->h_pos < mh_end(it->hash)) {
 		if (mh_exist(it->hash, it->h_pos))
-			return mh_lstrptr_node(it->hash, it->h_pos++)->val;
+			return (struct tuple *) mh_lstrptr_node(
+						it->hash,it->h_pos++)->val;
 		it->h_pos++;
 	}
 	return NULL;
@@ -139,48 +141,112 @@ hash_iterator_lstr_eq(struct iterator *it)
 
 /* {{{ HashIndex -- base class for all hashes. ********************/
 
-@interface Hash32Index: HashIndex {
-	 struct mh_i32ptr_t *int_hash;
+class Hash32Index: public HashIndex {
+public:
+	Hash32Index(struct key_def *key_def, struct space *space);
+	~Hash32Index();
+
+	virtual size_t
+	size() const;
+
+	virtual struct tuple *
+	random(u32 rnd) const;
+
+	virtual struct tuple *
+	findByKey(const void *key, u32 part_count) const;
+
+	virtual struct tuple *
+	replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		enum dup_replace_mode mode);
+
+	struct iterator *
+	allocIterator() const;
+
+	void
+	initIterator(struct iterator *iterator, enum iterator_type type,
+		     const void *key, u32 part_count) const;
+
+	virtual void
+	reserve(u32 n_tuples);
+private:
+	struct mh_i32ptr_t *int_hash;
 };
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg;
-@end
+class Hash64Index: public HashIndex {
+public:
+	Hash64Index(struct key_def *key_def, struct space *space);
+	~Hash64Index();
+
+	virtual size_t
+	size() const;
+
+	virtual struct tuple *
+	random(u32 rnd) const;
+
+	virtual struct tuple *
+	findByKey(const void *key, u32 part_count) const;
+
+	virtual struct tuple *
+	replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		enum dup_replace_mode mode);
 
-@interface Hash64Index: HashIndex {
+	struct iterator *
+	allocIterator() const;
+
+	void
+	initIterator(struct iterator *iterator, enum iterator_type type,
+		     const void *key, u32 part_count) const;
+
+	virtual void
+	reserve(u32 n_tuples);
+private:
 	struct mh_i64ptr_t *int64_hash;
 };
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg;
-@end
+class HashStrIndex: public HashIndex {
+public:
+	HashStrIndex(struct key_def *key_def, struct space *space);
+	~HashStrIndex();
 
-@interface HashStrIndex: HashIndex {
-	struct mh_lstrptr_t *str_hash;
-};
+	virtual size_t
+	size() const;
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg;
-@end
+	virtual struct tuple *
+	random(u32 rnd) const;
 
-@implementation HashIndex
+	virtual struct tuple *
+	findByKey(const void *key, u32 part_count) const;
 
-+ (struct index_traits *) traits
-{
-	return &hash_index_traits;
-}
+	virtual struct tuple *
+	replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		enum dup_replace_mode mode);
 
-+ (HashIndex *) alloc: (struct key_def *) key_def :(struct space *) space
-{
-	(void) space;
+	struct iterator *
+	allocIterator() const;
+
+	void
+	initIterator(struct iterator *iterator, enum iterator_type type,
+		     const void *key, u32 part_count) const;
+
+	virtual void
+	reserve(u32 n_tuples);
+private:
+	struct mh_lstrptr_t *str_hash;
+};
 
+HashIndex *
+HashIndex::factory(struct key_def *key_def, struct space *space)
+{
 	/*
 	 * Hash index always has a single-field key.
 	 */
 	switch (key_def->parts[0].type) {
 	case NUM:
-		return [Hash32Index alloc];  /* 32-bit integer hash */
+		return new Hash32Index(key_def, space);  /* 32-bit integer hash */
 	case NUM64:
-		return [Hash64Index alloc];  /* 64-bit integer hash */
+		return new Hash64Index(key_def, space);  /* 64-bit integer hash */
 	case STRING:
-		return [HashStrIndex alloc]; /* string hash */
+		return new HashStrIndex(key_def, space); /* string hash */
 	default:
 		assert(false);
 	}
@@ -188,75 +254,75 @@ hash_iterator_lstr_eq(struct iterator *it)
 	return NULL;
 }
 
-- (void) reserve: (u32) n_tuples
+HashIndex::HashIndex(struct key_def *key_def, struct space *space)
+	: Index(key_def, space)
 {
-	(void) n_tuples;
-	[self subclassResponsibility: _cmd];
+	/* Nothing */
 }
 
-- (void) beginBuild
+void
+HashIndex::beginBuild()
 {
 }
 
-- (void) buildNext: (struct tuple *)tuple
+void
+HashIndex::buildNext(struct tuple *tuple)
 {
-	[self replace: NULL :tuple :DUP_INSERT];
+	replace(NULL, tuple, DUP_INSERT);
 }
 
-- (void) endBuild
+void
+HashIndex::endBuild()
 {
 }
 
-- (void) build: (Index *) pk
+void
+HashIndex::build(Index *pk)
 {
-	u32 n_tuples = [pk size];
+	u32 n_tuples = pk->size();
 
 	if (n_tuples == 0)
 		return;
 
-	[self reserve: n_tuples];
+	reserve(n_tuples);
 
-	say_info("Adding %"PRIu32 " keys to HASH index %"
-		 PRIu32 "...", n_tuples, index_n(self));
+	say_info("Adding %" PRIu32 " keys to HASH index %"
+		 PRIu32 "...", n_tuples, index_n(this));
 
-	struct iterator *it = pk->position;
+	struct iterator *it = pk->primaryIterator();
 	struct tuple *tuple;
-	[pk initIterator: it :ITER_ALL :NULL :0];
+	pk->initIterator(it, ITER_ALL, NULL, 0);
 
 	while ((tuple = it->next(it)))
-	      [self replace: NULL :tuple :DUP_INSERT];
+	      replace(NULL, tuple, DUP_INSERT);
 }
 
-- (void) free
-{
-	[super free];
-}
-
-- (struct tuple *) min
+struct tuple *
+HashIndex::min() const
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "Hash index", "min()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "Hash index", "min()");
 	return NULL;
 }
 
-- (struct tuple *) max
+struct tuple *
+HashIndex::max() const
 {
-	tnt_raise(ClientError, :ER_UNSUPPORTED, "Hash index", "max()");
+	tnt_raise(ClientError, ER_UNSUPPORTED, "Hash index", "max()");
 	return NULL;
 }
 
-- (struct tuple *) findByTuple: (struct tuple *) tuple
+struct tuple *
+HashIndex::findByTuple(struct tuple *tuple) const
 {
 	assert(key_def->is_unique);
 	if (tuple->field_count < key_def->max_fieldno)
-		tnt_raise(IllegalParams, :"tuple must have all indexed fields");
+		tnt_raise(IllegalParams, "tuple must have all indexed fields");
 
 	/* Hash index currently is always single-part. */
 	void *field = tuple_field(tuple, key_def->parts[0].fieldno);
-	return [self findByKey :field :1];
+	return findByKey(field, 1);
 }
 
-@end
-
 /* }}} */
 
 /* {{{ Hash32Index ************************************************/
@@ -266,8 +332,8 @@ int32_key_to_node(const void *key)
 {
 	u32 key_size = load_varint32(&key);
 	if (key_size != 4)
-		tnt_raise(ClientError, :ER_KEY_FIELD_TYPE, "u32");
-	struct mh_i32ptr_node_t node = { .key = *(u32 *) key };
+		tnt_raise(ClientError, ER_KEY_FIELD_TYPE, "u32");
+	struct mh_i32ptr_node_t node = { *(u32 *) key, NULL };
 	return node;
 }
 
@@ -280,44 +346,42 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return node;
 }
 
-@implementation Hash32Index
 
-- (void) reserve: (u32) n_tuples
+Hash32Index::Hash32Index(struct key_def *key_def, struct space *space)
+	: HashIndex(key_def, space)
 {
-	mh_i32ptr_reserve(int_hash, n_tuples, NULL);
+	int_hash = mh_i32ptr_new();
 }
 
-- (void) free
+Hash32Index::~Hash32Index()
 {
 	mh_i32ptr_delete(int_hash);
-	[super free];
 }
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+void
+Hash32Index::reserve(u32 n_tuples)
 {
-	self = [super init: key_def_arg :space_arg];
-
-	if (self == NULL)
-		return NULL;
-
-	int_hash = mh_i32ptr_new();
-	return self;
+	mh_i32ptr_reserve(int_hash, n_tuples, NULL);
 }
 
-- (size_t) size
+size_t
+Hash32Index::size() const
 {
 	return mh_size(int_hash);
 }
 
-- (struct tuple *) random: (u32) rnd
+
+struct tuple *
+Hash32Index::random(u32 rnd) const
 {
 	mh_int_t k = mh_i32ptr_random(int_hash, rnd);
 	if (k != mh_end(int_hash))
-		return mh_i32ptr_node(int_hash, k)->val;
+		return (struct tuple *) mh_i32ptr_node(int_hash, k)->val;
 	return NULL;
 }
 
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count
+struct tuple *
+Hash32Index::findByKey(const void *key, u32 part_count) const
 {
 	assert(key_def->is_unique);
 	check_key_parts(key_def, part_count, false);
@@ -328,16 +392,16 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	struct mh_i32ptr_node_t node = int32_key_to_node(key);
 	mh_int_t k = mh_i32ptr_get(int_hash, &node, NULL);
 	if (k != mh_end(int_hash))
-		ret = mh_i32ptr_node(int_hash, k)->val;
+		ret = (struct tuple *) mh_i32ptr_node(int_hash, k)->val;
 #ifdef DEBUG
 	say_debug("Hash32Index find(self:%p, key:%i) = %p", self, node.key, ret);
 #endif
 	return ret;
 }
 
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  :(struct tuple *) new_tuple
-			  :(enum dup_replace_mode) mode
+struct tuple *
+Hash32Index::replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		     enum dup_replace_mode mode)
 {
 	struct mh_i32ptr_node_t new_node, old_node;
 	uint32_t errcode;
@@ -355,10 +419,12 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 		});
 
 		if (pos == mh_end(int_hash)) {
-			tnt_raise(LoggedError, :ER_MEMORY_ISSUE, (ssize_t) pos,
+			tnt_raise(LoggedError, ER_MEMORY_ISSUE, (ssize_t) pos,
 				  "int hash", "key");
 		}
-		struct tuple *dup_tuple = dup_node ? dup_node->val : NULL;
+		struct tuple *dup_tuple = dup_node
+				? (struct tuple *) dup_node->val
+				: NULL;
 		errcode = replace_check_dup(old_tuple, dup_tuple, mode);
 
 		if (errcode) {
@@ -371,7 +437,7 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 					      "recover of int hash");
 				}
 			}
-			tnt_raise(ClientError, :errcode, index_n(self));
+			tnt_raise(ClientError, errcode, index_n(this));
 		}
 		if (dup_tuple)
 			return dup_tuple;
@@ -384,9 +450,11 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 }
 
 
-- (struct iterator *) allocIterator
+struct iterator *
+Hash32Index::allocIterator() const
 {
-	struct hash_i32_iterator *it = malloc(sizeof(struct hash_i32_iterator));
+	struct hash_i32_iterator *it = (struct hash_i32_iterator *)
+			malloc(sizeof(struct hash_i32_iterator));
 	if (it) {
 		memset(it, 0, sizeof(*it));
 		it->base.next = hash_iterator_i32_ge;
@@ -395,8 +463,9 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return (struct iterator *) it;
 }
 
-- (void) initIterator: (struct iterator *) ptr :(enum iterator_type) type
-			:(const void *) key :(u32) part_count
+void
+Hash32Index::initIterator(struct iterator *ptr, enum iterator_type type,
+			  const void *key, u32 part_count) const
 {
 	assert(ptr->free == hash_iterator_free);
 	struct hash_i32_iterator *it = (struct hash_i32_iterator *) ptr;
@@ -406,7 +475,7 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	case ITER_GE:
 		if (key != NULL) {
 			check_key_parts(key_def, part_count,
-					traits->allows_partial_key);
+					hash_index_traits.allows_partial_key);
 			node = int32_key_to_node(key);
 			it->h_pos = mh_i32ptr_get(int_hash, &node, NULL);
 			it->base.next = hash_iterator_i32_ge;
@@ -419,18 +488,17 @@ int32_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 		break;
 	case ITER_EQ:
 		check_key_parts(key_def, part_count,
-				traits->allows_partial_key);
+				hash_index_traits.allows_partial_key);
 		node = int32_key_to_node(key);
 		it->h_pos = mh_i32ptr_get(int_hash, &node, NULL);
 		it->base.next = hash_iterator_i32_eq;
 		break;
 	default:
-		tnt_raise(ClientError, :ER_UNSUPPORTED,
+		tnt_raise(ClientError, ER_UNSUPPORTED,
 			  "Hash index", "requested iterator type");
 	}
 	it->hash = int_hash;
 }
-@end
 
 /* }}} */
 
@@ -441,8 +509,8 @@ int64_key_to_node(const void *key)
 {
 	u32 key_size = load_varint32(&key);
 	if (key_size != 8)
-		tnt_raise(ClientError, :ER_KEY_FIELD_TYPE, "u64");
-	struct mh_i64ptr_node_t node = { .key = *(u64 *) key };
+		tnt_raise(ClientError, ER_KEY_FIELD_TYPE, "u64");
+	struct mh_i64ptr_node_t node = { *(u64 *) key, NULL };
 	return node;
 }
 
@@ -455,60 +523,60 @@ int64_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return node;
 }
 
-@implementation Hash64Index
-- (void) reserve: (u32) n_tuples
+Hash64Index::Hash64Index(struct key_def *key_def, struct space *space)
+	: HashIndex(key_def, space)
 {
-	mh_i64ptr_reserve(int64_hash, n_tuples, NULL);
+	int64_hash = mh_i64ptr_new();
 }
 
-- (void) free
+Hash64Index::~Hash64Index()
 {
 	mh_i64ptr_delete(int64_hash);
-	[super free];
 }
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+void
+Hash64Index::reserve(u32 n_tuples)
 {
-	self = [super init: key_def_arg :space_arg];
-	if (self == NULL)
-		return NULL;
-
-	int64_hash = mh_i64ptr_new();
-	return self;
+	mh_i64ptr_reserve(int64_hash, n_tuples, NULL);
 }
 
-- (size_t) size
+size_t
+Hash64Index::size() const
 {
 	return mh_size(int64_hash);
 }
 
-- (struct tuple *) random: (u32) rnd
+struct tuple *
+Hash64Index::random(u32 rnd) const
 {
 	mh_int_t k = mh_i64ptr_random(int64_hash, rnd);
 	if (k != mh_end(int64_hash))
-		return mh_i64ptr_node(int64_hash, k)->val;
+		return (struct tuple *) mh_i64ptr_node(int64_hash, k)->val;
 	return NULL;
 }
 
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count
+struct tuple *
+Hash64Index::findByKey(const void *key, u32 part_count) const
 {
 	assert(key_def->is_unique);
 	check_key_parts(key_def, part_count, false);
 
+	(void) part_count;
+
 	struct tuple *ret = NULL;
 	struct mh_i64ptr_node_t node = int64_key_to_node(key);
 	mh_int_t k = mh_i64ptr_get(int64_hash, &node, NULL);
 	if (k != mh_end(int64_hash))
-		ret = mh_i64ptr_node(int64_hash, k)->val;
-#ifdef DEBUG
-	say_debug("Hash64Index find(self:%p, key:%"PRIu64") = %p", self, node.key, ret);
-#endif
+		ret = (struct tuple *) mh_i64ptr_node(int64_hash, k)->val;
+	#ifdef DEBUG
+	say_debug("Hash64Index find(self:%p, key:%i) = %p", self, node.key, ret);
+	#endif
 	return ret;
 }
 
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  :(struct tuple *) new_tuple
-			  :(enum dup_replace_mode) mode
+struct tuple *
+Hash64Index::replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		     enum dup_replace_mode mode)
 {
 	struct mh_i64ptr_node_t new_node, old_node;
 	uint32_t errcode;
@@ -517,59 +585,66 @@ int64_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 		struct mh_i64ptr_node_t *dup_node = &old_node;
 		new_node = int64_tuple_to_node(new_tuple, key_def);
 		mh_int_t pos = mh_i64ptr_put(int64_hash, &new_node,
-					     &dup_node, NULL);
+				 &dup_node, NULL);
 
 		ERROR_INJECT(ERRINJ_INDEX_ALLOC,
 		{
 			mh_i64ptr_del(int64_hash, pos, NULL);
 			pos = mh_end(int64_hash);
 		});
+
 		if (pos == mh_end(int64_hash)) {
-			tnt_raise(LoggedError, :ER_MEMORY_ISSUE, (ssize_t) pos,
-				  "int64 hash", "key");
+			tnt_raise(LoggedError, ER_MEMORY_ISSUE, (ssize_t) pos,
+				  "int hash", "key");
 		}
-		struct tuple *dup_tuple = dup_node ? dup_node->val : NULL;
+		struct tuple *dup_tuple = dup_node
+			? (struct tuple *) dup_node->val
+			: NULL;
 		errcode = replace_check_dup(old_tuple, dup_tuple, mode);
 
 		if (errcode) {
 			mh_i64ptr_remove(int64_hash, &new_node, NULL);
 			if (dup_node) {
-				pos = mh_i64ptr_put(int64_hash, dup_node,
-						    NULL, NULL);
+				pos = mh_i64ptr_put(int64_hash, dup_node, NULL, NULL);
 				if (pos == mh_end(int64_hash)) {
 					panic("Failed to allocate memory in "
-					      "recover of int64 hash");
+					      "recover of int hash");
 				}
 			}
-			tnt_raise(ClientError, :errcode, index_n(self));
+			tnt_raise(ClientError, errcode, index_n(this));
 		}
+
 		if (dup_tuple)
 			return dup_tuple;
 	}
+
 	if (old_tuple) {
 		old_node = int64_tuple_to_node(old_tuple, key_def);
 		mh_i64ptr_remove(int64_hash, &old_node, NULL);
 	}
+
 	return old_tuple;
 }
 
 
-- (struct iterator *) allocIterator
+struct iterator *
+Hash64Index::allocIterator() const
 {
-	struct hash_i64_iterator *it = malloc(sizeof(struct hash_i64_iterator));
+	struct hash_i64_iterator *it = (struct hash_i64_iterator *)
+			malloc(sizeof(struct hash_i64_iterator));
 	if (it) {
 		memset(it, 0, sizeof(*it));
 		it->base.next = hash_iterator_i64_ge;
 		it->base.free = hash_iterator_free;
 	}
+
 	return (struct iterator *) it;
 }
 
-
-- (void) initIterator: (struct iterator *) ptr :(enum iterator_type) type
-			:(const void *) key :(u32) part_count
+void
+Hash64Index::initIterator(struct iterator *ptr, enum iterator_type type,
+			  const void *key, u32 part_count) const
 {
-	(void) part_count;
 	assert(ptr->free == hash_iterator_free);
 	struct hash_i64_iterator *it = (struct hash_i64_iterator *) ptr;
 	struct mh_i64ptr_node_t node;
@@ -578,31 +653,30 @@ int64_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	case ITER_GE:
 		if (key != NULL) {
 			check_key_parts(key_def, part_count,
-					traits->allows_partial_key);
+					hash_index_traits.allows_partial_key);
 			node = int64_key_to_node(key);
 			it->h_pos = mh_i64ptr_get(int64_hash, &node, NULL);
 			it->base.next = hash_iterator_i64_ge;
 			break;
 		}
-		/* Fallthrough. */
+		/* Fall through. */
 	case ITER_ALL:
+		it->h_pos = mh_begin(int_hash);
 		it->base.next = hash_iterator_i64_ge;
-		it->h_pos = mh_begin(int64_hash);
 		break;
 	case ITER_EQ:
 		check_key_parts(key_def, part_count,
-				traits->allows_partial_key);
+			hash_index_traits.allows_partial_key);
 		node = int64_key_to_node(key);
 		it->h_pos = mh_i64ptr_get(int64_hash, &node, NULL);
 		it->base.next = hash_iterator_i64_eq;
 		break;
 	default:
-		tnt_raise(ClientError, :ER_UNSUPPORTED,
+		tnt_raise(ClientError, ER_UNSUPPORTED,
 			  "Hash index", "requested iterator type");
 	}
 	it->hash = int64_hash;
 }
-@end
 
 /* }}} */
 
@@ -613,59 +687,57 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 {
 	void *field = tuple_field(tuple, key_def->parts[0].fieldno);
 	if (field == NULL)
-		tnt_raise(ClientError, :ER_NO_SUCH_FIELD,
+		tnt_raise(ClientError, ER_NO_SUCH_FIELD,
 			  key_def->parts[0].fieldno);
 
-	struct mh_lstrptr_node_t node = { .key = field, .val = tuple };
+	struct mh_lstrptr_node_t node = { field, tuple };
 	return node;
 }
 
-
-@implementation HashStrIndex
-- (void) reserve: (u32) n_tuples
+HashStrIndex::HashStrIndex(struct key_def *key_def, struct space *space)
+	: HashIndex(key_def, space)
 {
-	mh_lstrptr_reserve(str_hash, n_tuples, NULL);
+	str_hash = mh_lstrptr_new();
 }
 
-- (void) free
+HashStrIndex::~HashStrIndex()
 {
 	mh_lstrptr_delete(str_hash);
-	[super free];
 }
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+void
+HashStrIndex::reserve(u32 n_tuples)
 {
-	self = [super init: key_def_arg :space_arg];
-	if (self == NULL)
-		return NULL;
-
-	str_hash = mh_lstrptr_new();
-	return self;
+	mh_lstrptr_reserve(str_hash, n_tuples, NULL);
 }
 
-- (size_t) size
+
+size_t
+HashStrIndex::size() const
 {
 	return mh_size(str_hash);
 }
 
-- (struct tuple *) random: (u32) rnd
+struct tuple *
+HashStrIndex::random(u32 rnd) const
 {
 	mh_int_t k = mh_lstrptr_random(str_hash, rnd);
 	if (k != mh_end(str_hash))
-		return mh_lstrptr_node(str_hash, k)->val;
+		return (struct tuple *) mh_lstrptr_node(str_hash, k)->val;
 	return NULL;
 }
 
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count
+struct tuple *
+HashStrIndex::findByKey(const void *key, u32 part_count) const
 {
 	assert(key_def->is_unique);
 	check_key_parts(key_def, part_count, false);
 
 	struct tuple *ret = NULL;
-	const struct mh_lstrptr_node_t node = { .key = key };
+	const struct mh_lstrptr_node_t node = { key, NULL };
 	mh_int_t k = mh_lstrptr_get(str_hash, &node, NULL);
 	if (k != mh_end(str_hash))
-		ret = mh_lstrptr_node(str_hash, k)->val;
+		ret = (struct tuple *) mh_lstrptr_node(str_hash, k)->val;
 #ifdef DEBUG
 	u32 key_size = load_varint32((const void **) &key);
 	say_debug("HashStrIndex find(self:%p, key:(%i)'%.*s') = %p",
@@ -674,9 +746,9 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return ret;
 }
 
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  :(struct tuple *) new_tuple
-			  :(enum dup_replace_mode) mode
+struct tuple *
+HashStrIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
+	enum dup_replace_mode mode)
 {
 	struct mh_lstrptr_node_t new_node, old_node;
 	uint32_t errcode;
@@ -694,10 +766,12 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 		});
 
 		if (pos == mh_end(str_hash)) {
-			tnt_raise(LoggedError, :ER_MEMORY_ISSUE, (ssize_t) pos,
+			tnt_raise(LoggedError, ER_MEMORY_ISSUE, (ssize_t) pos,
 				  "str hash", "key");
 		}
-		struct tuple *dup_tuple = dup_node ? dup_node->val : NULL;
+		struct tuple *dup_tuple = dup_node
+				? (struct tuple *) dup_node->val
+				: NULL;
 		errcode = replace_check_dup(old_tuple, dup_tuple, mode);
 
 		if (errcode) {
@@ -710,7 +784,7 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 					      "recover of str hash");
 				}
 			}
-			tnt_raise(ClientError, :errcode, index_n(self));
+			tnt_raise(ClientError, errcode, index_n(this));
 		}
 		if (dup_tuple)
 			return dup_tuple;
@@ -722,9 +796,11 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return old_tuple;
 }
 
-- (struct iterator *) allocIterator
+struct iterator *
+HashStrIndex::allocIterator() const
 {
-	struct hash_lstr_iterator *it = malloc(sizeof(struct hash_lstr_iterator));
+	struct hash_lstr_iterator *it = (struct hash_lstr_iterator *)
+			malloc(sizeof(struct hash_lstr_iterator));
 	if (it) {
 		memset(it, 0, sizeof(*it));
 		it->base.next = hash_iterator_lstr_ge;
@@ -733,10 +809,9 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	return (struct iterator *) it;
 }
 
-
-- (void) initIterator: (struct iterator *) ptr
-			:(enum iterator_type) type
-			:(const void *) key :(u32) part_count
+void
+HashStrIndex::initIterator(struct iterator *ptr, enum iterator_type type,
+			   const void *key, u32 part_count) const
 {
 	(void) part_count;
 
@@ -748,7 +823,7 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 	case ITER_GE:
 		if (key != NULL) {
 			check_key_parts(key_def, part_count,
-					traits->allows_partial_key);
+					hash_index_traits.allows_partial_key);
 			node.key = key;
 			it->h_pos = mh_lstrptr_get(str_hash, &node, NULL);
 			it->base.next = hash_iterator_lstr_ge;
@@ -761,18 +836,17 @@ lstrptr_tuple_to_node(struct tuple *tuple, struct key_def *key_def)
 		break;
 	case ITER_EQ:
 		check_key_parts(key_def, part_count,
-				traits->allows_partial_key);
+				hash_index_traits.allows_partial_key);
 		node.key = key;
 		it->h_pos = mh_lstrptr_get(str_hash, &node, NULL);
 		it->base.next = hash_iterator_lstr_eq;
 		break;
 	default:
-		tnt_raise(ClientError, :ER_UNSUPPORTED,
+		tnt_raise(ClientError, ER_UNSUPPORTED,
 			  "Hash index", "requested iterator type");
 	}
 	it->hash = str_hash;
 }
-@end
 
 /* }}} */
 
diff --git a/src/box/hash_index.h b/src/box/hash_index.h
index 5e1fd9c4388ffba03b5e953f1f89967bb99c3672..df0c5f8e23f02543682d29b05fcc16552150dbb6 100644
--- a/src/box/hash_index.h
+++ b/src/box/hash_index.h
@@ -31,14 +31,34 @@
 
 #include "index.h"
 
-@class Index;
 
-@interface HashIndex: Index
+class HashIndex: public Index {
+public:
+	static HashIndex *
+	factory(struct key_def *key_def, struct space *space);
 
-+ (struct index_traits *) traits;
-+ (HashIndex *) alloc: (struct key_def *) key_def :(struct space *) space;
+	HashIndex(struct key_def *key_def, struct space *space);
 
-- (void) reserve: (u32) n_tuples;
-@end
+	virtual void beginBuild();
+	virtual void buildNext(struct tuple *tuple);
+	virtual void endBuild();
+	virtual void build(Index *pk);
+	virtual size_t size() const  = 0;
+	virtual struct tuple *min() const;
+	virtual struct tuple *max() const;
+	virtual struct tuple *random(u32 rnd) const = 0;
+	virtual struct tuple *findByKey(const void *key, u32 part_count) const  = 0;
+	virtual struct tuple *findByTuple(struct tuple *tuple) const;
+	virtual struct tuple *replace(struct tuple *old_tuple,
+				      struct tuple *new_tuple,
+				      enum dup_replace_mode mode)  = 0;
+
+	virtual struct iterator *allocIterator() const = 0;
+	virtual void initIterator(struct iterator *iterator,
+				  enum iterator_type type,
+				  const void *key, u32 part_count) const  = 0;
+
+	virtual void reserve(u32 n_tuples) = 0;
+};
 
 #endif /* TARANTOOL_BOX_HASH_INDEX_H_INCLUDED */
diff --git a/src/box/index.m b/src/box/index.cc
similarity index 54%
rename from src/box/index.m
rename to src/box/index.cc
index 3e066376f2f1babe59f47eb006cc3c355bba2a2d..dfca3de0c84f4e5a3db40edc34fb165a9f39b511 100644
--- a/src/box/index.m
+++ b/src/box/index.cc
@@ -35,10 +35,6 @@
 #include "exception.h"
 #include "space.h"
 
-static struct index_traits index_traits = {
-	.allows_partial_key = false,
-};
-
 const char *field_data_type_strs[] = {"UNKNOWN", "NUM", "NUM64", "STR", "\0"};
 STRS(index_type, INDEX_TYPE);
 STRS(iterator_type, ITERATOR_TYPE);
@@ -46,14 +42,14 @@ STRS(iterator_type, ITERATOR_TYPE);
 /* {{{ Utilities. **********************************************/
 
 void
-check_key_parts(const struct key_def *key_def,
+Index::check_key_parts(const struct key_def *key_def,
 		u32 part_count, bool partial_key_allowed)
 {
 	if (part_count > key_def->part_count)
-		tnt_raise(ClientError, :ER_KEY_PART_COUNT,
+		tnt_raise(ClientError, ER_KEY_PART_COUNT,
 			  part_count, key_def->part_count);
 	if (!partial_key_allowed && part_count < key_def->part_count)
-		tnt_raise(ClientError, :ER_EXACT_MATCH,
+		tnt_raise(ClientError, ER_EXACT_MATCH,
 			  part_count, key_def->part_count);
 }
 
@@ -62,7 +58,7 @@ check_key_parts(const struct key_def *key_def,
  * allowed.
  */
 uint32_t
-replace_check_dup(struct tuple *old_tuple,
+Index::replace_check_dup(struct tuple *old_tuple,
 		  struct tuple *dup_tuple,
 		  enum dup_replace_mode mode)
 {
@@ -93,24 +89,16 @@ replace_check_dup(struct tuple *old_tuple,
 
 /* {{{ Index -- base class for all indexes. ********************/
 
-@implementation Index
-
-+ (struct index_traits *) traits
-{
-	return &index_traits;
-}
-
-+ (Index *) alloc: (enum index_type) type
-	 :(struct key_def *) key_def
-	 :(struct space *) space
+Index *
+Index::factory(enum index_type type, struct key_def *key_def, struct space *space)
 {
 	switch (type) {
 	case HASH:
-		return [HashIndex alloc: key_def :space];
+		return HashIndex::factory(key_def, space);
 	case TREE:
-		return [TreeIndex alloc: key_def :space];
+		return TreeIndex::factory(key_def, space);
 	case BITSET:
-		return [BitsetIndex alloc];
+		return new BitsetIndex(key_def, space);
 	default:
 		assert(false);
 	}
@@ -118,118 +106,28 @@ replace_check_dup(struct tuple *old_tuple,
 	return NULL;
 }
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
-{
-	self = [super init];
-	if (self == NULL)
-		return NULL;
-
-	traits = [object_getClass(self) traits];
-	key_def = key_def_arg;
-	space = space_arg;
-	position = [self allocIterator];
-
-	return self;
-}
-
-- (void) free
-{
-	position->free(position);
-	[super free];
-}
-
-- (void) beginBuild
-{
-	[self subclassResponsibility: _cmd];
-}
-
-- (void) buildNext: (struct tuple *)tuple
-{
-	(void) tuple;
-	[self subclassResponsibility: _cmd];
-}
-
-- (void) endBuild
-{
-	[self subclassResponsibility: _cmd];
-}
-
-- (void) build: (Index *) pk
+Index::Index(struct key_def *key_def, struct space *space)
 {
-	(void) pk;
-	[self subclassResponsibility: _cmd];
+	this->key_def = key_def;
+	this->space = space;
+	this->position = NULL;
 }
 
-
-- (size_t) size
+Index::~Index()
 {
-	[self subclassResponsibility: _cmd];
-	return 0;
-}
-
-- (struct tuple *) min
-{
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
-- (struct tuple *) max
-{
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
-- (struct tuple *) random: (u32) rnd
-{
-	(void) rnd;
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count
-{
-	(void) key;
-	(void) part_count;
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
-- (struct tuple *) findByTuple: (struct tuple *) pattern
-{
-	(void) pattern;
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  : (struct tuple *) new_tuple
-			  : (enum dup_replace_mode) mode
-{
-	(void) old_tuple;
-	(void) new_tuple;
-	(void) mode;
-	[self subclassResponsibility: _cmd];
-	return NULL;
+	if (position != NULL) {
+		position->free(position);
+	}
 }
 
-- (struct iterator *) allocIterator
+struct iterator *
+Index::primaryIterator()
 {
-	[self subclassResponsibility: _cmd];
-	return NULL;
-}
-
+	if (position == NULL) {
+		position = allocIterator();
+	}
 
-- (void) initIterator: (struct iterator *) iterator
-	:(enum iterator_type) type
-	:(const void *) key :(u32) part_count
-{
-	(void) iterator;
-	(void) type;
-	(void) key;
-	(void) part_count;
-	[self subclassResponsibility: _cmd];
+	return position;
 }
 
-@end
-
 /* }}} */
diff --git a/src/box/index.h b/src/box/index.h
index 9b024dc007c9d13570320c4576805450cfc9664a..f7a3ce74237de9a004b26f382fab5adcb9a79140 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -28,10 +28,11 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#import "object.h"
 #include <stdbool.h>
 #include <util.h>
 
+#include "object.h"
+
 struct tuple;
 struct space;
 
@@ -141,16 +142,16 @@ struct index_traits
  * possibly present in the index.
  */
 enum dup_replace_mode {
-        /**
+	/**
 	 * If a duplicate is found, delete it and insert
 	 * a new tuple instead. Otherwise, insert a new tuple.
-         */
+	 */
 	DUP_REPLACE_OR_INSERT,
 	/**
 	 * If a duplicate is found, produce an error.
 	 * I.e. require that no old key exists with the same
 	 * value.
-         */
+	 */
 	DUP_INSERT,
 	/**
 	 * Unless a duplicate exists, throw an error.
@@ -158,14 +159,76 @@ enum dup_replace_mode {
 	DUP_REPLACE
 };
 
-@interface Index: tnt_Object {
-	/* Index features. */
-	struct index_traits *traits;
- @public
+
+class Index: public Object {
+public:
+
 	/* Index owner space */
 	struct space *space;
 	/* Description of a possibly multipart key. */
 	struct key_def *key_def;
+
+
+	/**
+	 * Allocate index instance.
+	 *
+	 * @param type     index type
+	 * @param key_def  key part description
+	 * @param space    space the index belongs to
+	 */
+	static Index *factory(enum index_type type, struct key_def *key_def,
+		      struct space *space);
+
+	/**
+	 * Initialize index instance.
+	 *
+	 * @param key_def  key part description
+	 * @param space    space the index belongs to
+	 */
+protected:
+	Index(struct key_def *key_def, struct space *space);
+
+public:
+	virtual ~Index();
+
+	/**
+	 * Two-phase index creation: begin building, add tuples, finish.
+	 */
+	virtual void beginBuild() = 0;
+	virtual void buildNext(struct tuple *tuple) = 0;
+	virtual void endBuild() = 0;
+	/** Build this index based on the contents of another index. */
+	virtual void build(Index *pk) = 0;
+	virtual size_t size() const = 0;
+	virtual struct tuple *min() const = 0;
+	virtual struct tuple *max() const = 0;
+	virtual struct tuple *random(u32 rnd) const = 0;
+	virtual struct tuple *findByKey(const void *key, u32 part_count) const = 0;
+	virtual struct tuple *findByTuple(struct tuple *tuple) const = 0;
+	virtual struct tuple *replace(struct tuple *old_tuple,
+				      struct tuple *new_tuple,
+				      enum dup_replace_mode mode) = 0;
+	/**
+	 * Create a structure to represent an iterator. Must be
+	 * initialized separately.
+	 */
+	virtual struct iterator *allocIterator() const = 0;
+	virtual void initIterator(struct iterator *iterator,
+				  enum iterator_type type,
+				  const void *key, u32 part_count) const = 0;
+
+	struct iterator *primaryIterator();
+protected:
+	static void
+	check_key_parts(const struct key_def *key_def, u32 part_count,
+			bool partial_key_allowed);
+
+	static uint32_t
+	replace_check_dup(struct tuple *old_tuple,
+			  struct tuple *dup_tuple,
+			  enum dup_replace_mode mode);
+
+private:
 	/*
 	 * Pre-allocated iterator to speed up the main case of
 	 * box_process(). Should not be used elsewhere.
@@ -173,62 +236,4 @@ enum dup_replace_mode {
 	struct iterator *position;
 };
 
-/**
- * Get index traits.
- */
-+ (struct index_traits *) traits;
-/**
- * Allocate index instance.
- *
- * @param type     index type
- * @param key_def  key part description
- * @param space    space the index belongs to
- */
-+ (Index *) alloc: (enum index_type) type :(struct key_def *) key_def
-	:(struct space *) space;
-/**
- * Initialize index instance.
- *
- * @param key_def  key part description
- * @param space    space the index belongs to
- */
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg;
-/** Destroy and free index instance. */
-- (void) free;
-/**
- * Two-phase index creation: begin building, add tuples, finish.
- */
-- (void) beginBuild;
-- (void) buildNext: (struct tuple *)tuple;
-- (void) endBuild;
-/** Build this index based on the contents of another index. */
-- (void) build: (Index *) pk;
-- (size_t) size;
-- (struct tuple *) min;
-- (struct tuple *) max;
-- (struct tuple *) random: (u32) rnd;
-- (struct tuple *) findByKey: (const void *) key :(u32) part_count;
-- (struct tuple *) findByTuple: (struct tuple *) tuple;
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  :(struct tuple *) new_tuple
-			  :(enum dup_replace_mode) mode;
-/**
- * Create a structure to represent an iterator. Must be
- * initialized separately.
- */
-- (struct iterator *) allocIterator;
-- (void) initIterator: (struct iterator *) iterator
-		     :(enum iterator_type) type
-		     :(const void *) key :(u32) part_count;
-@end
-
-void
-check_key_parts(const struct key_def *key_def, u32 part_count,
-		bool partial_key_allowed);
-
-uint32_t
-replace_check_dup(struct tuple *old_tuple,
-		  struct tuple *dup_tuple,
-		  enum dup_replace_mode mode);
-
 #endif /* TARANTOOL_BOX_INDEX_H_INCLUDED */
diff --git a/src/box/port.m b/src/box/port.cc
similarity index 98%
rename from src/box/port.m
rename to src/box/port.cc
index f694530cdcac20a5bd2e4c135cc18b372fa07fbd..98a8c9654214710fc2d2b29e18579941c761988f 100644
--- a/src/box/port.m
+++ b/src/box/port.cc
@@ -46,6 +46,6 @@ static struct port_vtab port_null_vtab = {
 };
 
 struct port port_null = {
-	.vtab = &port_null_vtab,
+	/* .vtab = */ &port_null_vtab,
 };
 
diff --git a/src/box/request.m b/src/box/request.cc
similarity index 86%
rename from src/box/request.m
rename to src/box/request.cc
index 752833f015952475c984074432cb87ba5b8298ec..f4bd73b754fae68d499565b2ece542742439b9e5 100644
--- a/src/box/request.m
+++ b/src/box/request.cc
@@ -72,31 +72,31 @@ execute_replace(struct request *request, struct txn *txn)
 {
 	txn_add_redo(txn, request->type, request->data, request->len);
 	const void **reqpos = &request->data;
-	const void *reqend = request->data + request->len;
+	const void *reqend = (const char *) request->data + request->len;
 	struct space *sp = read_space(reqpos, reqend);
 	request->flags |= (pick_u32(reqpos, reqend) &
 			   BOX_ALLOWED_REQUEST_FLAGS);
 	size_t field_count = pick_u32(reqpos, reqend);
 
 	if (field_count == 0)
-		tnt_raise(IllegalParams, :"tuple field count is 0");
+		tnt_raise(IllegalParams, "tuple field count is 0");
 
-	size_t tuple_len = reqend - *reqpos;
+	size_t tuple_len = (const char *) reqend - (const char *) *reqpos;
 	if (tuple_len != valid_tuple(*reqpos, reqend, field_count))
-		tnt_raise(IllegalParams, :"incorrect tuple length");
+		tnt_raise(IllegalParams, "incorrect tuple length");
 
 	struct tuple *new_tuple = tuple_alloc(tuple_len);
 	new_tuple->field_count = field_count;
 	memcpy(new_tuple->data, *reqpos, tuple_len);
 
-	@try {
+	try {
 		space_validate_tuple(sp, new_tuple);
 		enum dup_replace_mode mode = dup_replace_mode(request->flags);
 		txn_replace(txn, sp, NULL, new_tuple, mode);
 
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		tuple_free(new_tuple);
-		@throw;
+		throw;
 	}
 }
 
@@ -236,7 +236,7 @@ struct update_field {
 	 * Length of the "tail" in the old tuple from end
 	 * of old data to the beginning of the field in the
 	 * next update_field structure.
-         */
+	 */
 	u32 tail_len;
 };
 
@@ -246,7 +246,7 @@ update_field_init(struct update_field *field,
 {
 	STAILQ_INIT(&field->ops);
 	field->old = old;
-	field->tail = old + old_len;
+	field->tail = (char *) old + old_len;
 	field->tail_len = tail_len;
 }
 
@@ -254,14 +254,15 @@ static inline u32
 update_field_len(struct update_field *f)
 {
 	struct update_op *last = STAILQ_LAST(&f->ops, update_op, next);
-	return last? last->new_field_len : f->tail - f->old;
+	return last ? last->new_field_len
+		    : (const char *) f->tail - (const char *) f->old;
 }
 
 static inline void
 op_check_field_no(u32 field_no, u32 field_max)
 {
 	if (field_no > field_max)
-		tnt_raise(ClientError, :ER_NO_SUCH_FIELD, field_no);
+		tnt_raise(ClientError, ER_NO_SUCH_FIELD, field_no);
 }
 
 static inline void
@@ -330,10 +331,10 @@ static void
 do_update_op_splice(struct op_splice_arg *arg, const void *in, void *out)
 {
 	memcpy(out, in, arg->offset);           /* copy field head. */
-	out += arg->offset;
+	out = (char *) out + arg->offset;
 	memcpy(out, arg->paste, arg->paste_length); /* copy the paste */
-	out += arg->paste_length;
-	memcpy(out, in + arg->tail_offset, arg->tail_length); /* copy tail */
+	out = (char *) out + arg->paste_length;
+	memcpy(out, (const char *) in + arg->tail_offset, arg->tail_length); /* copy tail */
 }
 
 static void
@@ -348,8 +349,8 @@ static void
 init_update_op_insert(struct rope *rope, struct update_op *op)
 {
 	op_adjust_field_no(op, rope_size(rope));
-	struct update_field *field = palloc(fiber->gc_pool,
-					    sizeof(struct update_field));
+	struct update_field *field = (struct update_field *)
+			palloc(fiber->gc_pool, sizeof(struct update_field));
 	update_field_init(field, op->arg.set.value, op->arg.set.length, 0);
 	rope_insert(rope, op->field_no, field, 1);
 }
@@ -358,8 +359,8 @@ static void
 init_update_op_set(struct rope *rope, struct update_op *op)
 {
 	if (op->field_no < rope_size(rope)) {
-		struct update_field *field = rope_extract(rope,
-							  op->field_no);
+		struct update_field *field = (struct update_field *)
+				rope_extract(rope, op->field_no);
 		/* Skip all previous ops. */
 		STAILQ_INIT(&field->ops);
 		STAILQ_INSERT_TAIL(&field->ops, op, next);
@@ -381,7 +382,8 @@ init_update_op_arith(struct rope *rope, struct update_op *op)
 {
 	op_check_field_no(op->field_no, rope_size(rope) - 1);
 
-	struct update_field *field = rope_extract(rope, op->field_no);
+	struct update_field *field = (struct update_field *)
+			rope_extract(rope, op->field_no);
 	struct op_arith_arg *arg = &op->arg.arith;
 	u32 field_len = update_field_len(field);
 
@@ -391,7 +393,7 @@ init_update_op_arith(struct rope *rope, struct update_op *op)
 
 		/* Check the operand type. */
 		if (op->arg.set.length != sizeof(i32))
-			tnt_raise(ClientError, :ER_ARG_TYPE,
+			tnt_raise(ClientError, ER_ARG_TYPE,
 				  "32-bit int");
 
 		arg->i32_val = *(i32 *)op->arg.set.value;
@@ -409,12 +411,12 @@ init_update_op_arith(struct rope *rope, struct update_op *op)
 			arg->i64_val = *(i64 *)op->arg.set.value;
 			break;
 		default:
-			tnt_raise(ClientError, :ER_ARG_TYPE,
+			tnt_raise(ClientError, ER_ARG_TYPE,
 				  "32-bit or 64-bit int");
 		}
 		break;
 	default:
-		tnt_raise(ClientError, :ER_FIELD_TYPE,
+		tnt_raise(ClientError, ER_FIELD_TYPE,
 			  "32-bit or 64-bit int");
 	}
 	STAILQ_INSERT_TAIL(&field->ops, op, next);
@@ -425,19 +427,20 @@ static void
 init_update_op_splice(struct rope *rope, struct update_op *op)
 {
 	op_check_field_no(op->field_no, rope_size(rope) - 1);
-	struct update_field *field = rope_extract(rope, op->field_no);
+	struct update_field *field = (struct update_field *)
+			rope_extract(rope, op->field_no);
 
 	u32 field_len = update_field_len(field);
 
 	struct op_splice_arg *arg = &op->arg.splice;
 	const void *value = op->arg.set.value;
-	const void *end = value + op->arg.set.length;
+	const void *end = (const char *) value + op->arg.set.length;
 
 	/* Read the offset. */
 	arg->offset = pick_field_u32(&value, end);
 	if (arg->offset < 0) {
 		if (-arg->offset > field_len)
-			tnt_raise(ClientError, :ER_SPLICE,
+			tnt_raise(ClientError, ER_SPLICE,
 				  "offset is out of bound");
 		arg->offset += field_len;
 	} else if (arg->offset > field_len) {
@@ -465,7 +468,7 @@ init_update_op_splice(struct rope *rope, struct update_op *op)
 
 	/* Check that the operands are fully read. */
 	if (value != end)
-		tnt_raise(IllegalParams, :"field splice format error");
+		tnt_raise(IllegalParams, "field splice format error");
 
 	/* Record the new field length. */
 	op->new_field_len = arg->offset + arg->paste_length + arg->tail_length;
@@ -487,7 +490,7 @@ static struct update_op_meta update_op_meta[UPDATE_OP_MAX + 1] = {
 static void *
 rope_alloc(void *ctx, size_t size)
 {
-	return palloc(ctx, size);
+	return palloc((struct palloc_pool *) ctx, size);
 }
 
 /** Free rope node - do nothing, since we use a pool allocator. */
@@ -502,20 +505,20 @@ static void *
 update_field_split(void *data, size_t size __attribute__((unused)),
 		   size_t offset)
 {
-	struct update_field *prev = data;
+	struct update_field *prev = (struct update_field *) data;
 
-	struct update_field *next = palloc(fiber->gc_pool,
-					   sizeof(struct update_field));
+	struct update_field *next = (struct update_field *)
+			palloc(fiber->gc_pool, sizeof(struct update_field));
 	assert(offset > 0 && prev->tail_len > 0);
 
 	const void *field = prev->tail;
-	const void *end = field + prev->tail_len;
+	const void *end = (const char *) field + prev->tail_len;
 
 	prev->tail_len = tuple_range_size(&field, end, offset - 1);
 	u32 field_len = load_varint32(&field);
 
-	update_field_init(next, field, field_len,
-			  end - field - field_len);
+	update_field_init(next, field, field_len, (const char *) end -
+			  (const char *) field - field_len);
 	return next;
 }
 
@@ -533,12 +536,13 @@ update_create_rope(struct update_op *op, struct update_op *op_end,
 
 	/* Initialize the rope with the old tuple. */
 
-	struct update_field *first = palloc(fiber->gc_pool,
-					    sizeof(struct update_field));
+	struct update_field *first = (struct update_field *)
+			palloc(fiber->gc_pool, sizeof(struct update_field));
 	const void *field = tuple->data;
 	const void *end = tuple->data + tuple->bsize;
 	u32 field_len = load_varint32(&field);
-	update_field_init(first, field, field_len, end - field - field_len);
+	update_field_init(first, field, field_len,
+			  (const char *) end - (const char *) field - field_len);
 
 	rope_append(rope, first, tuple->field_count);
 
@@ -557,14 +561,15 @@ update_calc_new_tuple_length(struct rope *rope)
 
 	rope_iter_create(&it, rope);
 	for (node = rope_iter_start(&it); node; node = rope_iter_next(&it)) {
-		struct update_field *field = rope_leaf_data(node);
+		struct update_field *field =
+				(struct update_field *) rope_leaf_data(node);
 		u32 field_len = update_field_len(field);
 		new_tuple_len += (varint32_sizeof(field_len) +
 				  field_len + field->tail_len);
 	}
 
 	if (new_tuple_len == 0)
-		tnt_raise(ClientError, :ER_TUPLE_IS_EMPTY);
+		tnt_raise(ClientError, ER_TUPLE_IS_EMPTY);
 
 	return new_tuple_len;
 }
@@ -572,8 +577,8 @@ update_calc_new_tuple_length(struct rope *rope)
 static void
 do_update_ops(struct rope *rope, struct tuple *new_tuple)
 {
-	void *new_data = new_tuple->data;
-	void *new_data_end = new_data + new_tuple->bsize;
+	char *new_data = (char *) new_tuple->data;
+	char *new_data_end = new_data + new_tuple->bsize;
 
 	new_tuple->field_count = 0;
 
@@ -583,11 +588,12 @@ do_update_ops(struct rope *rope, struct tuple *new_tuple)
 	rope_iter_create(&it, rope);
 	for (node = rope_iter_start(&it); node; node = rope_iter_next(&it)) {
 
-		struct update_field *field = rope_leaf_data(node);
+		struct update_field *field = (struct update_field *)
+				rope_leaf_data(node);
 		u32 field_count = rope_leaf_size(node);
 		u32 field_len = update_field_len(field);
 
-		new_data = pack_varint32(new_data, field_len);
+		new_data = (char *) pack_varint32(new_data, field_len);
 
 		const void *old_field = field->old;
 		void *new_field = (STAILQ_EMPTY(&field->ops) ?
@@ -643,12 +649,12 @@ static struct update_op *
 update_read_ops(const void **reqpos, const void *reqend, u32 op_cnt)
 {
 	if (op_cnt > BOX_UPDATE_OP_CNT_MAX)
-		tnt_raise(IllegalParams, :"too many operations for update");
+		tnt_raise(IllegalParams, "too many operations for update");
 	if (op_cnt == 0)
-		tnt_raise(IllegalParams, :"no operations for update");
+		tnt_raise(IllegalParams, "no operations for update");
 	/* Read update operations.  */
-	struct update_op *ops = palloc(fiber->gc_pool, op_cnt *
-				       sizeof(struct update_op));
+	struct update_op *ops = (struct update_op *) palloc(fiber->gc_pool,
+					op_cnt * sizeof(struct update_op));
 	struct update_op *op = ops, *ops_end = ops + op_cnt;
 	for (; op < ops_end; op++) {
 		/* Read operation */
@@ -656,7 +662,7 @@ update_read_ops(const void **reqpos, const void *reqend, u32 op_cnt)
 		op->opcode = pick_u8(reqpos, reqend);
 
 		if (op->opcode >= UPDATE_OP_MAX)
-			tnt_raise(ClientError, :ER_UNKNOWN_UPDATE_OP);
+			tnt_raise(ClientError, ER_UNKNOWN_UPDATE_OP);
 		op->meta = &update_op_meta[op->opcode];
 
 		op->arg.set.value = pick_field(reqpos, reqend);
@@ -664,7 +670,7 @@ update_read_ops(const void **reqpos, const void *reqend, u32 op_cnt)
 	}
 	/* Check the remainder length, the request must be fully read. */
 	if (*reqpos != reqend)
-		tnt_raise(IllegalParams, :"can't unpack request");
+		tnt_raise(IllegalParams, "can't unpack request");
 	return ops;
 }
 
@@ -673,7 +679,7 @@ execute_update(struct request *request, struct txn *txn)
 {
 	txn_add_redo(txn, request->type, request->data, request->len);
 	const void **reqpos = &request->data;
-	const void *reqend = request->data + request->len;
+	const void *reqend = (const char *) request->data + request->len;
 	struct space *sp = read_space(reqpos, reqend);
 	request->flags |= (pick_u32(reqpos, reqend) &
 			   BOX_ALLOWED_REQUEST_FLAGS);
@@ -684,7 +690,7 @@ execute_update(struct request *request, struct txn *txn)
 
 	Index *pk = space_index(sp, 0);
 	/* Try to find the tuple by primary key. */
-	struct tuple *old_tuple = [pk findByKey :key :key_part_count];
+	struct tuple *old_tuple = pk->findByKey(key, key_part_count);
 
 	if (old_tuple == NULL)
 		return;
@@ -698,14 +704,14 @@ execute_update(struct request *request, struct txn *txn)
 	size_t new_tuple_len = update_calc_new_tuple_length(rope);
 	struct tuple *new_tuple = tuple_alloc(new_tuple_len);
 
-	@try {
+	try {
 		do_update_ops(rope, new_tuple);
 		space_validate_tuple(sp, new_tuple);
 		txn_replace(txn, sp, old_tuple, new_tuple, DUP_INSERT);
 
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		tuple_free(new_tuple);
-		@throw;
+		throw;
 	}
 }
 
@@ -715,7 +721,7 @@ static void
 execute_select(struct request *request, struct port *port)
 {
 	const void **reqpos = &request->data;
-	const void *reqend = request->data + request->len;
+	const void *reqend = (const char *) request->data + request->len;
 	struct space *sp = read_space(reqpos, reqend);
 	u32 index_no = pick_u32(reqpos, reqend);
 	Index *index = index_find(sp, index_no);
@@ -723,7 +729,7 @@ execute_select(struct request *request, struct port *port)
 	u32 limit = pick_u32(reqpos, reqend);
 	u32 count = pick_u32(reqpos, reqend);
 	if (count == 0)
-		tnt_raise(IllegalParams, :"tuple count must be positive");
+		tnt_raise(IllegalParams, "tuple count must be positive");
 
 	ERROR_INJECT_EXCEPTION(ERRINJ_TESTING);
 
@@ -739,8 +745,8 @@ execute_select(struct request *request, struct port *port)
 		u32 key_part_count;
 		const void *key = read_key(reqpos, reqend, &key_part_count);
 
-		struct iterator *it = index->position;
-		[index initIterator: it :ITER_EQ :key :key_part_count];
+		struct iterator *it = index->primaryIterator();
+		index->initIterator(it, ITER_EQ, key, key_part_count);
 
 		struct tuple *tuple;
 		while ((tuple = it->next(it)) != NULL) {
@@ -756,7 +762,7 @@ execute_select(struct request *request, struct port *port)
 		}
 	}
 	if (*reqpos != reqend)
-		tnt_raise(IllegalParams, :"can't unpack request");
+		tnt_raise(IllegalParams, "can't unpack request");
 }
 
 static void
@@ -765,7 +771,7 @@ execute_delete(struct request *request, struct txn *txn)
 	u32 type = request->type;
 	txn_add_redo(txn, type, request->data, request->len);
 	const void **reqpos = &request->data;
-	const void *reqend = request->data + request->len;
+	const void *reqend = (const char *) request->data + request->len;
 	struct space *sp = read_space(reqpos, reqend);
 	if (type == DELETE) {
 		request->flags |= pick_u32(reqpos, reqend) &
@@ -776,7 +782,7 @@ execute_delete(struct request *request, struct txn *txn)
 	const void *key = read_key(reqpos, reqend, &key_part_count);
 	/* Try to find tuple by primary key */
 	Index *pk = space_index(sp, 0);
-	struct tuple *old_tuple = [pk findByKey :key :key_part_count];
+	struct tuple *old_tuple = pk->findByKey(key, key_part_count);
 
 	if (old_tuple == NULL)
 		return;
@@ -809,11 +815,12 @@ request_create(u32 type, const void *data, u32 len)
 {
 	if (request_check_type(type)) {
 		say_error("Unsupported request = %" PRIi32 "", type);
-		tnt_raise(IllegalParams, :"unsupported command code, "
+		tnt_raise(IllegalParams, "unsupported command code, "
 			  "check the error log");
 	}
 	request_check_type(type);
-	struct request *request = palloc(fiber->gc_pool, sizeof(struct request));
+	struct request *request = (struct request *)
+			palloc(fiber->gc_pool, sizeof(struct request));
 	request->type = type;
 	request->data = data;
 	request->len = len;
diff --git a/src/box/space.m b/src/box/space.cc
similarity index 81%
rename from src/box/space.m
rename to src/box/space.cc
index ba19094523e87d2637f19fc0672c9fc840095a4b..7b531bccff49a62c341910762c5899b14fe2ea78 100644
--- a/src/box/space.m
+++ b/src/box/space.cc
@@ -29,8 +29,10 @@
 #include "space.h"
 #include <stdlib.h>
 #include <string.h>
-#include <cfg/tarantool_box_cfg.h>
+extern "C" {
 #include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 #include <tarantool.h>
 #include <exception.h>
 #include "tuple.h"
@@ -52,10 +54,10 @@ space_create(u32 space_no, struct key_def *key_defs, u32 key_count, u32 arity)
 	struct space *space = space_by_n(space_no);
 	if (space)
 		panic("Space %d is already exists", space_no);
-	space = calloc(sizeof(struct space), 1);
+	space = (struct space *) calloc(sizeof(struct space), 1);
 	space->no = space_no;
 
-	const struct mh_i32ptr_node_t node = { .key = space->no, .val = space };
+	const struct mh_i32ptr_node_t node = { space->no, space };
 	mh_i32ptr_put(spaces, &node, NULL, NULL);
 
 	space->arity = arity;
@@ -70,11 +72,11 @@ space_create(u32 space_no, struct key_def *key_defs, u32 key_count, u32 arity)
 struct space *
 space_by_n(u32 n)
 {
-	const struct mh_i32ptr_node_t node = { .key = n };
+	const struct mh_i32ptr_node_t node = { n, NULL };
 	mh_int_t space = mh_i32ptr_get(spaces, &node, NULL);
 	if (space == mh_end(spaces))
 		return NULL;
-	return mh_i32ptr_node(spaces, space)->val;
+	return (struct space *) mh_i32ptr_node(spaces, space)->val;
 }
 
 /** Return the number of active indexes in a space. */
@@ -101,7 +103,8 @@ space_foreach(void (*func)(struct space *sp, void *udata), void *udata) {
 
 	mh_int_t i;
 	mh_foreach(spaces, i) {
-		struct space *space = mh_i32ptr_node(spaces, i)->val;
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
 		func(space, udata);
 	}
 }
@@ -127,7 +130,7 @@ space_replace(struct space *sp, struct tuple *old_tuple,
 	      struct tuple *new_tuple, enum dup_replace_mode mode)
 {
 	u32 i = 0;
-	@try {
+	try {
 		/* Update the primary key */
 		Index *pk = sp->index[0];
 		assert(pk->key_def->is_unique);
@@ -136,23 +139,23 @@ space_replace(struct space *sp, struct tuple *old_tuple,
 		 * has to find and delete it, or raise an
 		 * error.
 		 */
-		old_tuple = [pk replace: old_tuple :new_tuple :mode];
+		old_tuple = pk->replace(old_tuple, new_tuple, mode);
 
 		assert(old_tuple || new_tuple);
 		u32 n = index_count(sp);
 		/* Update secondary keys */
 		for (i = i + 1; i < n; i++) {
 			Index *index = sp->index[i];
-			[index replace: old_tuple :new_tuple :DUP_INSERT];
+			index->replace(old_tuple, new_tuple, DUP_INSERT);
 		}
 		return old_tuple;
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		/* Rollback all changes */
 		for (; i > 0; i--) {
 			Index *index = sp->index[i-1];
-			[index replace: new_tuple: old_tuple: DUP_INSERT];
+			index->replace(new_tuple, old_tuple, DUP_INSERT);
 		}
-		@throw;
+		throw;
 	}
 
 	assert(false);
@@ -165,11 +168,11 @@ space_validate_tuple(struct space *sp, struct tuple *new_tuple)
 	/* Check to see if the tuple has a sufficient number of fields. */
 	if (new_tuple->field_count < sp->max_fieldno)
 		tnt_raise(IllegalParams,
-			  :"tuple must have all indexed fields");
+			  "tuple must have all indexed fields");
 
 	if (sp->arity > 0 && sp->arity != new_tuple->field_count)
 		tnt_raise(IllegalParams,
-			  :"tuple field count must match space cardinality");
+			  "tuple field count must match space cardinality");
 
 	/* Sweep through the tuple and check the field sizes. */
 	const u8 *data = new_tuple->data;
@@ -183,11 +186,11 @@ space_validate_tuple(struct space *sp, struct tuple *new_tuple)
 		 */
 		if (sp->field_types[f] == NUM) {
 			if (len != sizeof(u32))
-				tnt_raise(ClientError, :ER_KEY_FIELD_TYPE,
+				tnt_raise(ClientError, ER_KEY_FIELD_TYPE,
 					  "u32");
 		} else if (sp->field_types[f] == NUM64) {
 			if (len != sizeof(u64))
-				tnt_raise(ClientError, :ER_KEY_FIELD_TYPE,
+				tnt_raise(ClientError, ER_KEY_FIELD_TYPE,
 					  "u64");
 		}
 	}
@@ -199,12 +202,13 @@ space_free(void)
 	mh_int_t i;
 
 	mh_foreach(spaces, i) {
-		struct space *space = mh_i32ptr_node(spaces, i)->val;
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
 		mh_i32ptr_del(spaces, i, NULL);
 
 		for (u32 j = 0 ; j < space->key_count; j++) {
 			Index *index = space->index[j];
-			[index free];
+			delete index;
 			key_free(&space->key_defs[j]);
 		}
 
@@ -227,7 +231,7 @@ key_init(struct key_def *def, struct tarantool_cfg_space_index *cfg_index)
 
 	/* Calculate key part count and maximal field number. */
 	for (u32 k = 0; cfg_index->key_field[k] != NULL; ++k) {
-		typeof(cfg_index->key_field[k]) cfg_key = cfg_index->key_field[k];
+		auto cfg_key = cfg_index->key_field[k];
 
 		if (cfg_key->fieldno == -1) {
 			/* last filled key reached */
@@ -239,14 +243,15 @@ key_init(struct key_def *def, struct tarantool_cfg_space_index *cfg_index)
 	}
 
 	/* init def array */
-	def->parts = malloc(sizeof(struct key_part) * def->part_count);
+	def->parts = (struct key_part *) malloc(sizeof(struct key_part) *
+						def->part_count);
 	if (def->parts == NULL) {
 		panic("can't allocate def parts array for index");
 	}
 
 	/* init compare order array */
 	def->max_fieldno++;
-	def->cmp_order = malloc(def->max_fieldno * sizeof(u32));
+	def->cmp_order = (u32 *) malloc(def->max_fieldno * sizeof(u32));
 	if (def->cmp_order == NULL) {
 		panic("can't allocate def cmp_order array for index");
 	}
@@ -256,7 +261,7 @@ key_init(struct key_def *def, struct tarantool_cfg_space_index *cfg_index)
 
 	/* fill fields and compare order */
 	for (u32 k = 0; cfg_index->key_field[k] != NULL; ++k) {
-		typeof(cfg_index->key_field[k]) cfg_key = cfg_index->key_field[k];
+		auto cfg_key = cfg_index->key_field[k];
 
 		if (cfg_key->fieldno == -1) {
 			/* last filled key reached */
@@ -295,7 +300,8 @@ space_init_field_types(struct space *space)
 
 	/* alloc & init field type info */
 	space->max_fieldno = max_fieldno;
-	space->field_types = calloc(max_fieldno, sizeof(enum field_data_type));
+	space->field_types = (enum field_data_type *)
+			     calloc(max_fieldno, sizeof(enum field_data_type));
 
 	/* extract field type info */
 	for (i = 0; i < key_count; i++) {
@@ -340,7 +346,7 @@ space_config()
 		if (space)
 			panic("space %u is already exists", i);
 
-		space = calloc(sizeof(struct space), 1);
+		space = (struct space *) calloc(sizeof(struct space), 1);
 		space->no = i;
 
 		space->arity = (cfg_space->cardinality != -1) ?
@@ -356,30 +362,29 @@ space_config()
 		}
 
 
-		space->key_defs = malloc(space->key_count *
-					    sizeof(struct key_def));
+		space->key_defs = (struct key_def *) malloc(space->key_count *
+							    sizeof(struct key_def));
 		if (space->key_defs == NULL) {
 			panic("can't allocate key def array");
 		}
 		for (u32 j = 0; cfg_space->index[j] != NULL; ++j) {
-			typeof(cfg_space->index[j]) cfg_index = cfg_space->index[j];
+			auto cfg_index = cfg_space->index[j];
 			key_init(&space->key_defs[j], cfg_index);
 		}
 		space_init_field_types(space);
 
 		/* fill space indexes */
 		for (u32 j = 0; cfg_space->index[j] != NULL; ++j) {
-			typeof(cfg_space->index[j]) cfg_index = cfg_space->index[j];
+			auto cfg_index = cfg_space->index[j];
 			enum index_type type = STR2ENUM(index_type, cfg_index->type);
 			struct key_def *key_def = &space->key_defs[j];
-			Index *index = [[Index alloc :type :key_def :space]
-					init :key_def :space];
+			Index *index = Index::factory(type, key_def, space);
 			assert (index != NULL);
 			space->index[j] = index;
 		}
 
 		const struct mh_i32ptr_node_t node =
-			{ .key = space->no, .val = space };
+			{ space->no, space };
 		mh_i32ptr_put(spaces, &node, NULL, NULL);
 		say_info("space %i successfully configured", i);
 	}
@@ -402,9 +407,10 @@ begin_build_primary_indexes(void)
 	mh_int_t i;
 
 	mh_foreach(spaces, i) {
-		struct space *space = mh_i32ptr_node(spaces, i)->val;
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
 		Index *index = space->index[0];
-		[index beginBuild];
+		index->beginBuild();
 	}
 }
 
@@ -413,9 +419,10 @@ end_build_primary_indexes(void)
 {
 	mh_int_t i;
 	mh_foreach(spaces, i) {
-		struct space *space = mh_i32ptr_node(spaces, i)->val;
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
 		Index *index = space->index[0];
-		[index endBuild];
+		index->endBuild();
 	}
 	primary_indexes_enabled = true;
 }
@@ -428,7 +435,8 @@ build_secondary_indexes(void)
 
 	mh_int_t i;
 	mh_foreach(spaces, i) {
-		struct space *space = mh_i32ptr_node(spaces, i)->val;
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
 
 		if (space->key_count <= 1)
 			continue; /* no secondary keys */
@@ -438,7 +446,7 @@ build_secondary_indexes(void)
 		Index *pk = space->index[0];
 		for (u32 j = 1; j < space->key_count; j++) {
 			Index *index = space->index[j];
-			[index build: pk];
+			index->build(pk);
 		}
 
 		say_info("Space %d: done", space->no);
@@ -457,10 +465,10 @@ check_spaces(struct tarantool_cfg *conf)
 	}
 
 	for (size_t i = 0; conf->space[i] != NULL; ++i) {
-		typeof(conf->space[i]) space = conf->space[i];
+		auto space = conf->space[i];
 
 		if (i >= BOX_SPACE_MAX) {
-			out_warning(0, "(space = %zu) invalid id, (maximum=%u)",
+			out_warning(CNF_OK, "(space = %zu) invalid id, (maximum=%u)",
 				    i, BOX_SPACE_MAX);
 			return -1;
 		}
@@ -476,7 +484,7 @@ check_spaces(struct tarantool_cfg *conf)
 		}
 
 		if (conf->memcached_port && i == conf->memcached_space) {
-			out_warning(0, "Space %zu is already used as "
+			out_warning(CNF_OK, "Space %zu is already used as "
 				    "memcached_space.", i);
 			return -1;
 		}
@@ -484,7 +492,7 @@ check_spaces(struct tarantool_cfg *conf)
 		/* at least one index in space must be defined
 		 * */
 		if (space->index == NULL) {
-			out_warning(0, "(space = %zu) "
+			out_warning(CNF_OK, "(space = %zu) "
 				    "at least one index must be defined", i);
 			return -1;
 		}
@@ -493,21 +501,21 @@ check_spaces(struct tarantool_cfg *conf)
 
 		/* check spaces indexes */
 		for (size_t j = 0; space->index[j] != NULL; ++j) {
-			typeof(space->index[j]) index = space->index[j];
+			auto index = space->index[j];
 			u32 key_part_count = 0;
 			enum index_type index_type;
 
 			/* check index bound */
 			if (j >= BOX_INDEX_MAX) {
 				/* maximum index in space reached */
-				out_warning(0, "(space = %zu index = %zu) "
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
 					    "too many indexed (%u maximum)", i, j, BOX_INDEX_MAX);
 				return -1;
 			}
 
 			/* at least one key in index must be defined */
 			if (index->key_field == NULL) {
-				out_warning(0, "(space = %zu index = %zu) "
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
 					    "at least one field must be defined", i, j);
 				return -1;
 			}
@@ -515,12 +523,12 @@ check_spaces(struct tarantool_cfg *conf)
 			/* check unique property */
 			if (index->unique == -1) {
 				/* unique property undefined */
-				out_warning(0, "(space = %zu index = %zu) "
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
 					    "unique property is undefined", i, j);
 			}
 
 			for (size_t k = 0; index->key_field[k] != NULL; ++k) {
-				typeof(index->key_field[k]) key = index->key_field[k];
+				auto key = index->key_field[k];
 
 				if (key->fieldno == -1) {
 					/* last key reached */
@@ -529,7 +537,7 @@ check_spaces(struct tarantool_cfg *conf)
 
 				if (key->fieldno >= BOX_FIELD_MAX) {
 					/* maximum index in space reached */
-					out_warning(0, "(space = %zu index = %zu) "
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
 						    "invalid field number (%u maximum)",
 						    i, j, BOX_FIELD_MAX);
 					return -1;
@@ -537,7 +545,7 @@ check_spaces(struct tarantool_cfg *conf)
 
 				/* key must has valid type */
 				if (STR2ENUM(field_data_type, key->type) == field_data_type_MAX) {
-					out_warning(0, "(space = %zu index = %zu) "
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
 						    "unknown field data type: `%s'", i, j, key->type);
 					return -1;
 				}
@@ -551,7 +559,7 @@ check_spaces(struct tarantool_cfg *conf)
 
 			/* Check key part count. */
 			if (key_part_count == 0) {
-				out_warning(0, "(space = %zu index = %zu) "
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
 					    "at least one field must be defined", i, j);
 				return -1;
 			}
@@ -560,14 +568,14 @@ check_spaces(struct tarantool_cfg *conf)
 
 			/* check index type */
 			if (index_type == index_type_MAX) {
-				out_warning(0, "(space = %zu index = %zu) "
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
 					    "unknown index type '%s'", i, j, index->type);
 				return -1;
 			}
 
 			/* First index must be unique. */
 			if (j == 0 && index->unique == false) {
-				out_warning(0, "(space = %zu) space first index must be unique", i);
+				out_warning(CNF_OK, "(space = %zu) space first index must be unique", i);
 				return -1;
 			}
 
@@ -576,14 +584,14 @@ check_spaces(struct tarantool_cfg *conf)
 				/* check hash index */
 				/* hash index must has single-field key */
 				if (key_part_count != 1) {
-					out_warning(0, "(space = %zu index = %zu) "
-					            "hash index must has a single-field key", i, j);
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "hash index must has a single-field key", i, j);
 					return -1;
 				}
 				/* hash index must be unique */
 				if (!index->unique) {
-					out_warning(0, "(space = %zu index = %zu) "
-					            "hash index must be unique", i, j);
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "hash index must be unique", i, j);
 					return -1;
 				}
 				break;
@@ -594,13 +602,13 @@ check_spaces(struct tarantool_cfg *conf)
 				/* check bitset index */
 				/* bitset index must has single-field key */
 				if (key_part_count != 1) {
-					out_warning(0, "(space = %zu index = %zu) "
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
 						    "bitset index must has a single-field key", i, j);
 					return -1;
 				}
 				/* bitset index must not be unique */
 				if (index->unique) {
-					out_warning(0, "(space = %zu index = %zu) "
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
 						    "bitset index must be non-unique", i, j);
 					return -1;
 				}
@@ -612,12 +620,12 @@ check_spaces(struct tarantool_cfg *conf)
 
 		/* Check for index field type conflicts */
 		if (max_key_fieldno > 0) {
-			char *types = alloca(max_key_fieldno);
+			char *types = (char *) alloca(max_key_fieldno);
 			memset(types, 0, max_key_fieldno);
 			for (size_t j = 0; space->index[j] != NULL; ++j) {
-				typeof(space->index[j]) index = space->index[j];
+				auto index = space->index[j];
 				for (size_t k = 0; index->key_field[k] != NULL; ++k) {
-					typeof(index->key_field[k]) key = index->key_field[k];
+					auto key = index->key_field[k];
 					if (key->fieldno == -1)
 						break;
 
@@ -628,7 +636,7 @@ check_spaces(struct tarantool_cfg *conf)
 						if (types[f] == UNKNOWN) {
 							types[f] = t;
 						} else {
-							out_warning(0, "(space = %zu fieldno = %zu) "
+							out_warning(CNF_OK, "(space = %zu fieldno = %zu) "
 								    "index field type mismatch", i, f);
 							return -1;
 						}
diff --git a/src/box/space.h b/src/box/space.h
index e06fbf8410e595be7f8726cd440967226ed7eaab..7f60c6913e280ab2f2790fa4bc104e732b02f88e 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -214,7 +214,7 @@ space_find(u32 space_no)
 	if (s)
 		return s;
 
-	tnt_raise(ClientError, :ER_NO_SUCH_SPACE, space_no);
+	tnt_raise(ClientError, ER_NO_SUCH_SPACE, space_no);
 }
 
 
@@ -283,7 +283,7 @@ index_find(struct space *sp, u32 index_no)
 {
 	Index *idx = space_index(sp, index_no);
 	if (idx == NULL)
-		tnt_raise(LoggedError, :ER_NO_SUCH_INDEX, index_no,
+		tnt_raise(LoggedError, ER_NO_SUCH_INDEX, index_no,
 			  space_n(sp));
 	return idx;
 }
diff --git a/src/box/tree_index.m b/src/box/tree_index.cc
similarity index 75%
rename from src/box/tree_index.m
rename to src/box/tree_index.cc
index ae76152321f946cae23801c352d21da8b58be948..c0fd07060a00a1dc91509e3116ba03b3e8f7ce5d 100644
--- a/src/box/tree_index.m
+++ b/src/box/tree_index.cc
@@ -36,7 +36,7 @@
 /* {{{ Utilities. *************************************************/
 
 static struct index_traits tree_index_traits = {
-	.allows_partial_key = true,
+	/* .allows_partial_key = */ true,
 };
 
 /**
@@ -320,12 +320,12 @@ fold_with_sparse_parts(struct key_def *key_def, struct tuple *tuple, union spars
 		if (part != BOX_FIELD_MAX) {
 			if (key_def->parts[part].type == NUM) {
 				if (len != sizeof parts[part].num32) {
-					tnt_raise(IllegalParams, :"key is not u32");
+					tnt_raise(IllegalParams, "key is not u32");
 				}
 				memcpy(&parts[part].num32, data, len);
 			} else if (key_def->parts[part].type == NUM64) {
 				if (len != sizeof parts[part].num64) {
-					tnt_raise(IllegalParams, :"key is not u64");
+					tnt_raise(IllegalParams, "key is not u64");
 				}
 				memcpy(&parts[part].num64, data, len);
 			} else if (len <= sizeof(parts[part].str.data)) {
@@ -359,11 +359,11 @@ fold_with_key_parts(struct key_def *key_def, struct key_data *key_data)
 
 		if (key_def->parts[part].type == NUM) {
 			if (len != sizeof parts[part].num32)
-				tnt_raise(IllegalParams, :"key is not u32");
+				tnt_raise(IllegalParams, "key is not u32");
 			memcpy(&parts[part].num32, data, len);
 		} else if (key_def->parts[part].type == NUM64) {
 			if (len != sizeof parts[part].num64)
-				tnt_raise(IllegalParams, :"key is not u64");
+				tnt_raise(IllegalParams, "key is not u64");
 			memcpy(&parts[part].num64, data, len);
 		} else if (len <= sizeof(parts[part].str.data)) {
 			parts[part].str.length = len;
@@ -556,7 +556,7 @@ dense_node_compare(struct key_def *key_def, u32 first_field,
 	assert(first_field + part_count <= tuple_b->field_count);
 
 	/* Allocate space for offsets. */
-	u32 *off_a = alloca(2 * part_count * sizeof(u32));
+	u32 *off_a = (u32 *) alloca(2 * part_count * sizeof(u32));
 	u32 *off_b = off_a + part_count;
 
 	/* Find field offsets. */
@@ -580,8 +580,8 @@ dense_node_compare(struct key_def *key_def, u32 first_field,
 		u32 field = key_def->parts[part].fieldno;
 		u8 *ad = tuple_a->data + off_a[field - first_field];
 		u8 *bd = tuple_b->data + off_b[field - first_field];
-		u32 al = load_varint32((void *) &ad);
-		u32 bl = load_varint32((void *) &bd);
+		u32 al = load_varint32((const void **) &ad);
+		u32 bl = load_varint32((const void **) &bd);
 		int r = dense_part_compare(key_def->parts[part].type,
 					   ad, al, bd, bl);
 		if (r) {
@@ -674,7 +674,7 @@ dense_key_node_compare(struct key_def *key_def,
 	assert(first_field + part_count <= tuple->field_count);
 
 	/* Allocate space for offsets. */
-	u32 *off = alloca(part_count * sizeof(u32));
+	u32 *off = (u32 *) alloca(part_count * sizeof(u32));
 
 	/* Find field offsets. */
 	off[0] = offset;
@@ -693,7 +693,7 @@ dense_key_node_compare(struct key_def *key_def,
 	for (u32 part = 0; part < part_count; ++part) {
 		u32 field = key_def->parts[part].fieldno;
 		const u8 *bd = tuple->data + off[field - first_field];
-		u32 bl = load_varint32((void *) &bd);
+		u32 bl = load_varint32((const void **) &bd);
 		int r = dense_key_part_compare(key_def->parts[part].type,
 					       key_data->data,
 					       key_data->parts[part],
@@ -723,7 +723,7 @@ linear_key_node_compare(struct key_def *key_def,
 		part_count = key_data->part_count;
 	u8 *bd = tuple->data + offset;
 	for (u32 part = 0; part < part_count; ++part) {
-		u32 bl = load_varint32((void *) &bd);
+		u32 bl = load_varint32((const void **) &bd);
 		int r = dense_key_part_compare(key_def->parts[part].type,
 					       key_data->data,
 					       key_data->parts[part],
@@ -742,7 +742,7 @@ linear_key_node_compare(struct key_def *key_def,
 
 struct tree_iterator {
 	struct iterator base;
-	TreeIndex *index;
+	const TreeIndex *index;
 	struct sptree_index_iterator *iter;
 	struct key_data key_data;
 };
@@ -771,7 +771,7 @@ tree_iterator_ge(struct iterator *iterator)
 {
 	struct tree_iterator *it = tree_iterator(iterator);
 	void *node = sptree_index_iterator_next(it->iter);
-	return [it->index unfold: node];
+	return it->index->unfold(node);
 }
 
 static struct tuple *
@@ -779,7 +779,7 @@ tree_iterator_le(struct iterator *iterator)
 {
 	struct tree_iterator *it = tree_iterator(iterator);
 	void *node = sptree_index_iterator_reverse_next(it->iter);
-	return [it->index unfold: node];
+	return it->index->unfold(node);
 }
 
 static struct tuple *
@@ -788,8 +788,9 @@ tree_iterator_eq(struct iterator *iterator)
 	struct tree_iterator *it = tree_iterator(iterator);
 
 	void *node = sptree_index_iterator_next(it->iter);
-	if (node && it->index->tree.compare(&it->key_data, node, it->index) == 0)
-		return [it->index unfold: node];
+	if (node && it->index->tree.compare(&it->key_data, node,
+					    (void *) it->index) == 0)
+		return it->index->unfold(node);
 
 	return NULL;
 }
@@ -801,8 +802,9 @@ tree_iterator_req(struct iterator *iterator)
 
 	void *node = sptree_index_iterator_reverse_next(it->iter);
 	if (node != NULL
-	    && it->index->tree.compare(&it->key_data, node, it->index) == 0) {
-		return [it->index unfold: node];
+	    && it->index->tree.compare(&it->key_data, node,
+				       (void *) it->index) == 0) {
+		return it->index->unfold(node);
 	}
 
 	return NULL;
@@ -816,9 +818,9 @@ tree_iterator_lt(struct iterator *iterator)
 	void *node ;
 	while ((node = sptree_index_iterator_reverse_next(it->iter)) != NULL) {
 		if (it->index->tree.compare(&it->key_data, node,
-					    it->index) != 0) {
+					    (void *) it->index) != 0) {
 			it->base.next = tree_iterator_le;
-			return [it->index unfold: node];
+			return it->index->unfold(node);
 		}
 	}
 
@@ -833,9 +835,9 @@ tree_iterator_gt(struct iterator *iterator)
 	void *node;
 	while ((node = sptree_index_iterator_next(it->iter)) != NULL) {
 		if (it->index->tree.compare(&it->key_data, node,
-					    it->index) != 0) {
+					    (void *) it->index) != 0) {
 			it->base.next = tree_iterator_ge;
-			return [it->index unfold: node];
+			return it->index->unfold(node);
 		}
 	}
 
@@ -846,186 +848,266 @@ tree_iterator_gt(struct iterator *iterator)
 
 /* {{{ TreeIndex -- base tree index class *************************/
 
-@class SparseTreeIndex;
-@class DenseTreeIndex;
-@class Num32TreeIndex;
-@class FixedTreeIndex;
+class SparseTreeIndex: public TreeIndex {
+public:
+	SparseTreeIndex(struct key_def *key_def, struct space *space);
 
-@interface SparseTreeIndex: TreeIndex
-@end
+// protected:
+	size_t
+	node_size() const;
 
-@interface DenseTreeIndex: TreeIndex {
-	@public
+	tree_cmp_t
+	node_cmp() const;
+
+	tree_cmp_t
+	dup_node_cmp() const;
+
+	tree_cmp_t
+	key_node_cmp() const;
+
+	void
+	fold(void *node, struct tuple *tuple) const;
+
+	struct tuple *
+	unfold(const void *node) const;
+};
+
+
+class DenseTreeIndex: public TreeIndex {
+public:
+	DenseTreeIndex(struct key_def *key_def, struct space *space);
+
+// protected:
+	size_t
+	node_size() const;
+
+	tree_cmp_t
+	node_cmp() const;
+
+	tree_cmp_t
+	dup_node_cmp() const;
+
+	tree_cmp_t
+	key_node_cmp() const;
+
+	void
+	fold(void *node, struct tuple *tuple) const;
+
+	struct tuple *
+	unfold(const void *node) const;
+
+//private:
 	u32 first_field;
-}
-@end
+};
+
+class Num32TreeIndex: public TreeIndex {
+public:
+	Num32TreeIndex(struct key_def *key_def, struct space *space);
+
+// protected:
+	size_t
+	node_size() const;
+
+	tree_cmp_t
+	node_cmp() const;
+
+	tree_cmp_t
+	dup_node_cmp() const;
 
-@interface Num32TreeIndex: TreeIndex
-@end
+	tree_cmp_t
+	key_node_cmp() const;
 
-@interface FixedTreeIndex: TreeIndex {
-	@public
+	void
+	fold(void *node, struct tuple *tuple) const;
+
+	struct tuple *
+	unfold(const void *node) const;
+};
+
+
+class FixedTreeIndex: public TreeIndex {
+public:
+	FixedTreeIndex(struct key_def *key_def, struct space *space);
+
+protected:
+	size_t
+	node_size() const;
+
+	tree_cmp_t
+	node_cmp() const;
+
+	tree_cmp_t
+	dup_node_cmp() const;
+
+	tree_cmp_t
+	key_node_cmp() const;
+
+	void
+	fold(void *node, struct tuple *tuple) const;
+
+	struct tuple *
+	unfold(const void *node) const;
+//private:
+public:
 	u32 first_field;
 	u32 first_offset;
-}
-@end
-
-@implementation TreeIndex
+};
 
-+ (struct index_traits *) traits
-{
-	return &tree_index_traits;
-}
 
-+ (Index *) alloc: (struct key_def *) key_def :(struct space *) space
+TreeIndex *
+TreeIndex::factory(struct key_def *key_def, struct space *space)
 {
 	enum tree_type type = find_tree_type(space, key_def);
 	switch (type) {
 	case TREE_SPARSE:
-		return [SparseTreeIndex alloc];
+		return new SparseTreeIndex(key_def, space);
 	case TREE_DENSE:
-		return [DenseTreeIndex alloc];
+		return new DenseTreeIndex(key_def, space);
 	case TREE_NUM32:
-		return [Num32TreeIndex alloc];
+		return new Num32TreeIndex(key_def, space);
 	case TREE_FIXED:
-		return [FixedTreeIndex alloc];
+		return new FixedTreeIndex(key_def, space);
 	default:
 		assert(false);
 		return 0;
 	}
 }
 
-- (void) free
+TreeIndex::TreeIndex(struct key_def *key_def, struct space *space)
+	: Index(key_def, space)
 {
-	sptree_index_destroy(&tree);
-	[super free];
+	memset(&tree, 0, sizeof tree);
 }
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+TreeIndex::~TreeIndex()
 {
-	self = [super init: key_def_arg :space_arg];
-	if (self == NULL)
-		return NULL;
-
-	memset(&tree, 0, sizeof tree);
-	return self;
+	sptree_index_destroy(&tree);
 }
 
-- (size_t) size
+size_t
+TreeIndex::size() const
 {
 	return tree.size;
 }
 
-- (struct tuple *) min
+struct tuple *
+TreeIndex::min() const
 {
 	void *node = sptree_index_first(&tree);
-	return [self unfold: node];
+	return unfold(node);
 }
 
-- (struct tuple *) max
+struct tuple *
+TreeIndex::max() const
 {
 	void *node = sptree_index_last(&tree);
-	return [self unfold: node];
+	return unfold(node);
 }
 
-- (struct tuple *) random: (u32) rnd
+struct tuple *
+TreeIndex::random(u32 rnd) const
 {
 	void *node = sptree_index_random(&tree, rnd);
-	return [self unfold: node];
+	return unfold(node);
 }
 
-- (struct tuple *) findByKey: (const void *) key : (u32) part_count
+struct tuple *
+TreeIndex::findByKey(const void *key, u32 part_count) const
 {
 	assert(key_def->is_unique);
 	check_key_parts(key_def, part_count, false);
 
-	struct key_data *key_data
-		= alloca(sizeof(struct key_data) +
+	struct key_data *key_data = (struct key_data *)
+			alloca(sizeof(struct key_data) +
 			 _SIZEOF_SPARSE_PARTS(part_count));
 
-	key_data->data = key;
+	key_data->data = (const u8 *) key;
 	key_data->part_count = part_count;
 	fold_with_key_parts(key_def, key_data);
 
 	void *node = sptree_index_find(&tree, key_data);
-	return [self unfold: node];
+	return unfold(node);
 }
 
-- (struct tuple *) findByTuple: (struct tuple *) tuple
+struct tuple *
+TreeIndex::findByTuple(struct tuple *tuple) const
 {
 	assert(key_def->is_unique);
 	if (tuple->field_count < key_def->max_fieldno)
-		tnt_raise(IllegalParams, :"tuple must have all indexed fields");
+		tnt_raise(IllegalParams, "tuple must have all indexed fields");
 
-	struct key_data *key_data
-		= alloca(sizeof(struct key_data) + _SIZEOF_SPARSE_PARTS(tuple->field_count));
+	struct key_data *key_data = (struct key_data *)
+			alloca(sizeof(struct key_data) +
+			       _SIZEOF_SPARSE_PARTS(tuple->field_count));
 
 	key_data->data = tuple->data;
 	key_data->part_count = tuple->field_count;
 	fold_with_sparse_parts(key_def, tuple, key_data->parts);
 
 	void *node = sptree_index_find(&tree, key_data);
-	return [self unfold: node];
+	return unfold(node);
 }
 
-- (struct tuple *) replace: (struct tuple *) old_tuple
-			  :(struct tuple *) new_tuple
-			  :(enum dup_replace_mode) mode
+struct tuple *
+TreeIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
+		   enum dup_replace_mode mode)
 {
-	size_t node_size = [self node_size];
+	size_t node_size = this->node_size();
 	void *new_node = alloca(node_size);
 	void *old_node = alloca(node_size);
 	uint32_t errcode;
 
 	if (new_tuple) {
 		void *dup_node = old_node;
-		[self fold: new_node :new_tuple];
+		fold(new_node, new_tuple);
 
 		/* Try to optimistically replace the new_tuple. */
 		sptree_index_replace(&tree, new_node, &dup_node);
 
-		struct tuple *dup_tuple = [self unfold: dup_node];
+		struct tuple *dup_tuple = unfold(dup_node);
 		errcode = replace_check_dup(old_tuple, dup_tuple, mode);
 
 		if (errcode) {
 			sptree_index_delete(&tree, new_node);
 			if (dup_node)
 				sptree_index_replace(&tree, dup_node, NULL);
-			tnt_raise(ClientError, :errcode, index_n(self));
+			tnt_raise(ClientError, errcode, index_n(this));
 		}
 		if (dup_tuple)
 			return dup_tuple;
 	}
 	if (old_tuple) {
-		[self fold: old_node :old_tuple];
+		fold(old_node, old_tuple);
 		sptree_index_delete(&tree, old_node);
 	}
 	return old_tuple;
 }
 
-- (struct iterator *) allocIterator
+struct iterator *
+TreeIndex::allocIterator() const
 {
 	assert(key_def->part_count);
-	struct tree_iterator *it
-		= malloc(sizeof(struct tree_iterator) + SIZEOF_SPARSE_PARTS(key_def));
+	struct tree_iterator *it = (struct tree_iterator *)
+			malloc(sizeof(struct tree_iterator) +
+			       SIZEOF_SPARSE_PARTS(key_def));
 
 	if (it) {
 		memset(it, 0, sizeof(struct tree_iterator));
-		it->index = self;
+		it->index = this;
 		it->base.free = tree_iterator_free;
 	}
 	return (struct iterator *) it;
 }
 
-- (void) initIterator: (struct iterator *) iterator
-	:(enum iterator_type) type
-	:(const void *) key :(u32) part_count
+void
+TreeIndex::initIterator(struct iterator *iterator, enum iterator_type type,
+			const void *key, u32 part_count) const
 {
 	struct tree_iterator *it = tree_iterator(iterator);
 
 	if (part_count != 0) {
 		check_key_parts(key_def, part_count,
-				traits->allows_partial_key);
+				tree_index_traits.allows_partial_key);
 	} else {
 		/*
 		 * If no key is specified, downgrade equality
@@ -1034,7 +1116,7 @@ tree_iterator_gt(struct iterator *iterator)
 		type = iterator_type_is_reverse(type) ? ITER_LE : ITER_GE;
 		key = NULL;
 	}
-	it->key_data.data = key;
+	it->key_data.data = (const u8 *) key;
 	it->key_data.part_count = part_count;
 
 	fold_with_key_parts(key_def, &it->key_data);
@@ -1067,29 +1149,31 @@ tree_iterator_gt(struct iterator *iterator)
 		it->base.next = tree_iterator_lt;
 		break;
 	default:
-		tnt_raise(ClientError, :ER_UNSUPPORTED,
+		tnt_raise(ClientError, ER_UNSUPPORTED,
 			  "Tree index", "requested iterator type");
 	}
 }
 
-- (void) beginBuild
+void
+TreeIndex::beginBuild()
 {
-	assert(index_is_primary(self));
+	assert(index_is_primary(this));
 
 	tree.size = 0;
 	tree.max_size = 64;
 
-	size_t node_size = [self node_size];
+	size_t node_size = this->node_size();
 	size_t sz = tree.max_size * node_size;
 	tree.members = malloc(sz);
 	if (tree.members == NULL) {
-		panic("malloc(): failed to allocate %"PRI_SZ" bytes", sz);
+		panic("malloc(): failed to allocate %" PRI_SZ " bytes", sz);
 	}
 }
 
-- (void) buildNext: (struct tuple *) tuple
+void
+TreeIndex::buildNext(struct tuple *tuple)
 {
-	size_t node_size = [self node_size];
+	size_t node_size = this->node_size();
 
 	if (tree.size == tree.max_size) {
 		tree.max_size *= 2;
@@ -1097,34 +1181,36 @@ tree_iterator_gt(struct iterator *iterator)
 		size_t sz = tree.max_size * node_size;
 		tree.members = realloc(tree.members, sz);
 		if (tree.members == NULL) {
-			panic("malloc(): failed to allocate %"PRI_SZ" bytes", sz);
+			panic("malloc(): failed to allocate %" PRI_SZ " bytes", sz);
 		}
 	}
 
 	void *node = ((u8 *) tree.members + tree.size * node_size);
-	[self fold: node :tuple];
+	fold(node, tuple);
 	tree.size++;
 }
 
-- (void) endBuild
+void
+TreeIndex::endBuild()
 {
-	assert(index_is_primary(self));
+	assert(index_is_primary(this));
 
 	u32 n_tuples = tree.size;
 	u32 estimated_tuples = tree.max_size;
 	void *nodes = tree.members;
 
 	sptree_index_init(&tree,
-			  [self node_size], nodes, n_tuples, estimated_tuples,
-			  [self key_node_cmp], [self node_cmp],
-			  self);
+			  node_size(), nodes, n_tuples, estimated_tuples,
+			  key_node_cmp(), node_cmp(),
+			  this);
 }
 
-- (void) build: (Index *) pk
+void
+TreeIndex::build(Index *pk)
 {
-	u32 n_tuples = [pk size];
+	u32 n_tuples = pk->size();
 	u32 estimated_tuples = n_tuples * 1.2;
-	size_t node_size = [self node_size];
+	size_t node_size = this->node_size();
 
 	void *nodes = NULL;
 	if (n_tuples) {
@@ -1136,73 +1222,33 @@ tree_iterator_gt(struct iterator *iterator)
 		size_t sz = estimated_tuples * node_size;
 		nodes = malloc(sz);
 		if (nodes == NULL) {
-			panic("malloc(): failed to allocate %"PRI_SZ" bytes", sz);
+			panic("malloc(): failed to allocate %" PRI_SZ " bytes", sz);
 		}
 	}
 
-	struct iterator *it = pk->position;
-	[pk initIterator: it :ITER_ALL :NULL :0];
+	struct iterator *it = pk->primaryIterator();
+	pk->initIterator(it, ITER_ALL, NULL, 0);
 
 	struct tuple *tuple;
 
 	for (u32 i = 0; (tuple = it->next(it)) != NULL; ++i) {
 		void *node = ((u8 *) nodes + i * node_size);
-		[self fold: node :tuple];
+		fold(node, tuple);
 	}
 
 	if (n_tuples) {
-		say_info("Sorting %"PRIu32 " keys in index %" PRIu32 "...", n_tuples,
-			 index_n(self));
+		say_info("Sorting %" PRIu32 " keys in index %" PRIu32 "...", n_tuples,
+			 index_n(this));
 	}
 
 	/* If n_tuples == 0 then estimated_tuples = 0, elem == NULL, tree is empty */
 	sptree_index_init(&tree,
 			  node_size, nodes, n_tuples, estimated_tuples,
-			  [self key_node_cmp],
-			  key_def->is_unique ? [self node_cmp] : [self dup_node_cmp],
-			  self);
-}
-
-- (size_t) node_size
-{
-	[self subclassResponsibility: _cmd];
-	return 0;
-}
-
-- (tree_cmp_t) node_cmp
-{
-	[self subclassResponsibility: _cmd];
-	return 0;
-}
-
-- (tree_cmp_t) dup_node_cmp
-{
-	[self subclassResponsibility: _cmd];
-	return 0;
-}
-
-- (tree_cmp_t) key_node_cmp
-{
-	[self subclassResponsibility: _cmd];
-	return 0;
-}
-
-- (void) fold: (void *) node :(struct tuple *) tuple
-{
-	(void) node;
-	(void) tuple;
-	[self subclassResponsibility: _cmd];
-}
-
-- (struct tuple *) unfold: (const void *) node
-{
-	(void) node;
-	[self subclassResponsibility: _cmd];
-	return NULL;
+			  key_node_cmp(),
+			  key_def->is_unique ? node_cmp() : dup_node_cmp(),
+			  this);
 }
 
-@end
-
 /* }}} */
 
 /* {{{ SparseTreeIndex ********************************************/
@@ -1211,8 +1257,8 @@ static int
 sparse_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	SparseTreeIndex *index = (SparseTreeIndex *) arg;
-	const struct sparse_node *node_xa = node_a;
-	const struct sparse_node *node_xb = node_b;
+	const struct sparse_node *node_xa = (const struct sparse_node *) node_a;
+	const struct sparse_node *node_xb = (const struct sparse_node *) node_b;
 	return sparse_node_compare(index->key_def,
 				   node_xa->tuple, node_xa->parts,
 				   node_xb->tuple, node_xb->parts);
@@ -1223,8 +1269,10 @@ sparse_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	int r = sparse_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct sparse_node *node_xa = node_a;
-		const struct sparse_node *node_xb = node_b;
+		const struct sparse_node *node_xa =
+				(const struct sparse_node *) node_a;
+		const struct sparse_node *node_xb =
+				(const struct sparse_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1234,49 +1282,58 @@ static int
 sparse_key_node_cmp(const void *key, const void *node, void *arg)
 {
 	SparseTreeIndex *index = (SparseTreeIndex *) arg;
-	const struct key_data *key_data = key;
-	const struct sparse_node *node_x = node;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct sparse_node *node_x = (const struct sparse_node *) node;
 	return sparse_key_node_compare(index->key_def, key_data,
 				       node_x->tuple, node_x->parts);
 }
 
-@implementation SparseTreeIndex
+SparseTreeIndex::SparseTreeIndex(struct key_def *key_def, struct space *space)
+	: TreeIndex(key_def, space)
+{
+	/* Nothing */
+}
 
-- (size_t) node_size
+size_t
+SparseTreeIndex::node_size() const
 {
 	return sizeof(struct sparse_node) + SIZEOF_SPARSE_PARTS(key_def);
 }
 
-- (tree_cmp_t) node_cmp
+
+tree_cmp_t
+SparseTreeIndex::node_cmp() const
 {
 	return sparse_node_cmp;
 }
 
-- (tree_cmp_t) dup_node_cmp
+tree_cmp_t
+SparseTreeIndex::dup_node_cmp() const
 {
 	return sparse_dup_node_cmp;
 }
 
-- (tree_cmp_t) key_node_cmp
+tree_cmp_t
+SparseTreeIndex::key_node_cmp() const
 {
 	return sparse_key_node_cmp;
 }
 
-- (void) fold: (void *) node :(struct tuple *) tuple
+void
+SparseTreeIndex::fold(void *node, struct tuple *tuple) const
 {
-	struct sparse_node *node_x = node;
+	struct sparse_node *node_x = (struct sparse_node *) node;
 	node_x->tuple = tuple;
 	fold_with_sparse_parts(key_def, tuple, node_x->parts);
 }
 
-- (struct tuple *) unfold: (const void *) node
+struct tuple *
+SparseTreeIndex::unfold(const void *node) const
 {
-	const struct sparse_node *node_x = node;
+	const struct sparse_node *node_x = (const struct sparse_node *) node;
 	return node_x ? node_x->tuple : NULL;
 }
 
-@end
-
 /* }}} */
 
 /* {{{ DenseTreeIndex *********************************************/
@@ -1285,8 +1342,8 @@ static int
 dense_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	DenseTreeIndex *index = (DenseTreeIndex *) arg;
-	const struct dense_node *node_xa = node_a;
-	const struct dense_node *node_xb = node_b;
+	const struct dense_node *node_xa = (const struct dense_node *) node_a;
+	const struct dense_node *node_xb = (const struct dense_node *) node_b;
 	return dense_node_compare(index->key_def, index->first_field,
 				  node_xa->tuple, node_xa->offset,
 				  node_xb->tuple, node_xb->offset);
@@ -1297,8 +1354,10 @@ dense_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	int r = dense_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct dense_node *node_xa = node_a;
-		const struct dense_node *node_xb = node_b;
+		const struct dense_node *node_xa =
+				(const struct dense_node *) node_a;
+		const struct dense_node *node_xb =
+				(const struct dense_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1308,8 +1367,8 @@ static int
 dense_key_node_cmp(const void *key, const void * node, void *arg)
 {
 	DenseTreeIndex *index = (DenseTreeIndex *) arg;
-	const struct key_data *key_data = key;
-	const struct dense_node *node_x = node;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct dense_node *node_x = (const struct dense_node *) node;
 	return dense_key_node_compare(index->key_def, key_data,
 				      index->first_field,
 				      node_x->tuple, node_x->offset);
@@ -1319,8 +1378,8 @@ static int
 linear_dense_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	DenseTreeIndex *index = (DenseTreeIndex *) arg;
-	const struct dense_node *node_xa = node_a;
-	const struct dense_node *node_xb = node_b;
+	const struct dense_node *node_xa = (const struct dense_node *) node_a;
+	const struct dense_node *node_xb = (const struct dense_node *) node_b;
 	return linear_node_compare(index->key_def, index->first_field,
 				   node_xa->tuple, node_xa->offset,
 				   node_xb->tuple, node_xb->offset);
@@ -1331,8 +1390,10 @@ linear_dense_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	int r = linear_dense_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct dense_node *node_xa = node_a;
-		const struct dense_node *node_xb = node_b;
+		const struct dense_node *node_xa =
+				(const struct dense_node *) node_a;
+		const struct dense_node *node_xb =
+				(const struct dense_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1342,66 +1403,65 @@ static int
 linear_dense_key_node_cmp(const void *key, const void * node, void *arg)
 {
 	DenseTreeIndex *index = (DenseTreeIndex *) arg;
-	const struct key_data *key_data = key;
-	const struct dense_node *node_x = node;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct dense_node *node_x = (const struct dense_node *) node;
 	return linear_key_node_compare(index->key_def, key_data,
 				       index->first_field,
 				       node_x->tuple, node_x->offset);
 }
 
-@implementation DenseTreeIndex
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+DenseTreeIndex::DenseTreeIndex(struct key_def *key_def, struct space *space)
+	: TreeIndex(key_def, space)
 {
-	self = [super init: key_def_arg :space_arg];
-	if (self == NULL)
-		return NULL;
-
 	first_field = find_first_field(key_def);
-	return self;
 }
 
-- (size_t) node_size
+size_t
+DenseTreeIndex::node_size() const
 {
 	return sizeof(struct dense_node);
 }
 
-- (tree_cmp_t) node_cmp
+tree_cmp_t
+DenseTreeIndex::node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_dense_node_cmp
 		: dense_node_cmp;
 }
 
-- (tree_cmp_t) dup_node_cmp
+tree_cmp_t
+DenseTreeIndex::dup_node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_dense_dup_node_cmp
 		: dense_dup_node_cmp;
 }
 
-- (tree_cmp_t) key_node_cmp
+tree_cmp_t
+DenseTreeIndex::key_node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_dense_key_node_cmp
 		: dense_key_node_cmp;
 }
 
-- (void) fold: (void *) node :(struct tuple *) tuple
+void
+DenseTreeIndex::fold(void *node, struct tuple *tuple) const
 {
-	struct dense_node *node_x = node;
+	struct dense_node *node_x = (struct dense_node *) node;
 	node_x->tuple = tuple;
 	node_x->offset = fold_with_dense_offset(key_def, tuple);
 }
 
-- (struct tuple *) unfold: (const void *) node
+struct tuple *
+DenseTreeIndex::unfold(const void *node) const
 {
-	const struct dense_node *node_x = node;
+	const struct dense_node *node_x = (const struct dense_node *) node;
 	return node_x ? node_x->tuple : NULL;
 }
 
-@end
-
 /* }}} */
 
 /* {{{ Num32TreeIndex *********************************************/
@@ -1410,8 +1470,8 @@ static int
 num32_node_cmp(const void * node_a, const void * node_b, void *arg)
 {
 	(void) arg;
-	const struct num32_node *node_xa = node_a;
-	const struct num32_node *node_xb = node_b;
+	const struct num32_node *node_xa = (const struct num32_node *) node_a;
+	const struct num32_node *node_xb = (const struct num32_node *) node_b;
 	return u32_cmp(node_xa->value, node_xb->value);
 }
 
@@ -1420,8 +1480,10 @@ num32_dup_node_cmp(const void * node_a, const void * node_b, void *arg)
 {
 	int r = num32_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct num32_node *node_xa = node_a;
-		const struct num32_node *node_xb = node_b;
+		const struct num32_node *node_xa =
+				(const struct num32_node *) node_a;
+		const struct num32_node *node_xb =
+				(const struct num32_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1431,50 +1493,58 @@ static int
 num32_key_node_cmp(const void * key, const void * node, void *arg)
 {
 	(void) arg;
-	const struct key_data *key_data = key;
-	const struct num32_node *node_x = node;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct num32_node *node_x = (const struct num32_node *) node;
 	if (key_data->part_count)
 		return u32_cmp(key_data->parts[0].num32, node_x->value);
 	return 0;
 }
 
-@implementation Num32TreeIndex
+Num32TreeIndex::Num32TreeIndex(struct key_def *key_def, struct space *space)
+	: TreeIndex(key_def, space)
+{
+	/* Nothing */
+}
 
-- (size_t) node_size
+size_t
+Num32TreeIndex::node_size() const
 {
 	return sizeof(struct num32_node);
 }
 
-- (tree_cmp_t) node_cmp
+tree_cmp_t
+Num32TreeIndex::node_cmp() const
 {
 	return num32_node_cmp;
 }
 
-- (tree_cmp_t) dup_node_cmp
+tree_cmp_t
+Num32TreeIndex::dup_node_cmp() const
 {
 	return num32_dup_node_cmp;
 }
 
-- (tree_cmp_t) key_node_cmp
+tree_cmp_t
+Num32TreeIndex::key_node_cmp() const
 {
 	return num32_key_node_cmp;
 }
 
-- (void) fold: (void *) node :(struct tuple *) tuple
+void
+Num32TreeIndex::fold(void *node, struct tuple *tuple) const
 {
 	struct num32_node *node_x = (struct num32_node *) node;
 	node_x->tuple = tuple;
 	node_x->value = fold_with_num32_value(key_def, tuple);
 }
 
-- (struct tuple *) unfold: (const void *) node
+struct tuple *
+Num32TreeIndex::unfold(const void *node) const
 {
-	const struct num32_node *node_x = node;
+	const struct num32_node *node_x = (const struct num32_node *) node;
 	return node_x ? node_x->tuple : NULL;
 }
 
-@end
-
 /* }}} */
 
 /* {{{ FixedTreeIndex *********************************************/
@@ -1483,8 +1553,8 @@ static int
 fixed_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	FixedTreeIndex *index = (FixedTreeIndex *) arg;
-	const struct fixed_node *node_xa = node_a;
-	const struct fixed_node *node_xb = node_b;
+	const struct fixed_node *node_xa = (const struct fixed_node *) node_a;
+	const struct fixed_node *node_xb = (const struct fixed_node *) node_b;
 	return dense_node_compare(index->key_def, index->first_field,
 				  node_xa->tuple, index->first_offset,
 				  node_xb->tuple, index->first_offset);
@@ -1495,8 +1565,10 @@ fixed_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	int r = fixed_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct fixed_node *node_xa = node_a;
-		const struct fixed_node *node_xb = node_b;
+		const struct fixed_node *node_xa =
+				(const struct fixed_node *) node_a;
+		const struct fixed_node *node_xb =
+				(const struct fixed_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1506,8 +1578,8 @@ static int
 fixed_key_node_cmp(const void *key, const void * node, void *arg)
 {
 	FixedTreeIndex *index = (FixedTreeIndex *) arg;
-	const struct key_data *key_data = key;
-	const struct fixed_node *node_x = node;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct fixed_node *node_x = (const struct fixed_node *) node;
 	return dense_key_node_compare(index->key_def, key_data,
 				      index->first_field,
 				      node_x->tuple, index->first_offset);
@@ -1517,8 +1589,8 @@ static int
 linear_fixed_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	FixedTreeIndex *index = (FixedTreeIndex *) arg;
-	const struct fixed_node *node_xa = node_a;
-	const struct fixed_node *node_xb = node_b;
+	const struct fixed_node *node_xa = (const struct fixed_node *) node_a;
+	const struct fixed_node *node_xb = (const struct fixed_node *) node_b;
 	return linear_node_compare(index->key_def, index->first_field,
 				   node_xa->tuple, index->first_offset,
 				   node_xb->tuple, index->first_offset);
@@ -1529,8 +1601,10 @@ linear_fixed_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 {
 	int r = linear_fixed_node_cmp(node_a, node_b, arg);
 	if (r == 0) {
-		const struct fixed_node *node_xa = node_a;
-		const struct fixed_node *node_xb = node_b;
+		const struct fixed_node *node_xa =
+				(const struct fixed_node *) node_a;
+		const struct fixed_node *node_xb =
+				(const struct fixed_node *) node_b;
 		r = ta_cmp(node_xa->tuple, node_xb->tuple);
 	}
 	return r;
@@ -1539,66 +1613,66 @@ linear_fixed_dup_node_cmp(const void *node_a, const void *node_b, void *arg)
 static int
 linear_fixed_key_node_cmp(const void *key, const void * node, void *arg)
 {
-	FixedTreeIndex *index = (FixedTreeIndex *) arg;
-	const struct key_data *key_data = key;
-	const struct fixed_node *node_x = node;
+	const FixedTreeIndex *index = (const FixedTreeIndex *) arg;
+	const struct key_data *key_data = (const struct key_data *) key;
+	const struct fixed_node *node_x = (const struct fixed_node *) node;
 	return linear_key_node_compare(index->key_def, key_data,
 					 index->first_field,
 					 node_x->tuple, index->first_offset);
 }
 
-@implementation FixedTreeIndex
 
-- (id) init: (struct key_def *) key_def_arg :(struct space *) space_arg
+FixedTreeIndex::FixedTreeIndex(struct key_def *key_def, struct space *space)
+	: TreeIndex(key_def, space)
 {
-	self = [super init: key_def_arg :space_arg];
-	if (self == NULL)
-		return NULL;
-
 	first_field = find_first_field(key_def);
 	first_offset = find_fixed_offset(space, first_field, 0);
-	return self;
 }
 
-- (size_t) node_size
+
+size_t
+FixedTreeIndex::node_size() const
 {
 	return sizeof(struct fixed_node);
 }
 
-- (tree_cmp_t) node_cmp
+tree_cmp_t
+FixedTreeIndex::node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_fixed_node_cmp
 		: fixed_node_cmp;
 }
 
-- (tree_cmp_t) dup_node_cmp
+tree_cmp_t
+FixedTreeIndex::dup_node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_fixed_dup_node_cmp
 		: fixed_dup_node_cmp;
 }
 
-- (tree_cmp_t) key_node_cmp
+tree_cmp_t
+FixedTreeIndex::key_node_cmp() const
 {
 	return key_is_linear(key_def)
 		? linear_fixed_key_node_cmp
 		: fixed_key_node_cmp;
 }
 
-- (void) fold: (void *) node :(struct tuple *) tuple
+void
+FixedTreeIndex::fold(void *node, struct tuple *tuple) const
 {
 	struct fixed_node *node_x = (struct fixed_node *) node;
 	node_x->tuple = tuple;
 }
 
-- (struct tuple *) unfold: (const void *) node
+struct tuple *
+FixedTreeIndex::unfold(const void *node) const
 {
-	const struct fixed_node *node_x = node;
+	const struct fixed_node *node_x = (const struct fixed_node *) node;
 	return node_x ? node_x->tuple : NULL;
 }
 
-@end
-
 /* }}} */
 
diff --git a/src/box/tree_index.h b/src/box/tree_index.h
index d1ff337d802d97e5592d16e46b3619757880cfb6..58b0829dca1ad27c29c25ff953326c5a40f5dac7 100644
--- a/src/box/tree_index.h
+++ b/src/box/tree_index.h
@@ -40,22 +40,45 @@ SPTREE_DEF(index, realloc);
 
 typedef int (*tree_cmp_t)(const void *, const void *, void *);
 
-@interface TreeIndex: Index {
-@public
-	sptree_index tree;
-};
+class TreeIndex: public Index {
+public:
+	static TreeIndex *
+	factory(struct key_def *key_def, struct space *space);
+
+	virtual void beginBuild();
+	virtual void buildNext(struct tuple *tuple);
+	virtual void endBuild();
+	virtual void build(Index *pk);
+	virtual size_t size() const;
+	virtual struct tuple *min() const;
+	virtual struct tuple *max() const;
+	virtual struct tuple *random(u32 rnd) const;
+	virtual struct tuple *findByKey(const void *key, u32 part_count) const;
+	virtual struct tuple *findByTuple(struct tuple *tuple) const;
+	virtual struct tuple *replace(struct tuple *old_tuple,
+				      struct tuple *new_tuple,
+				      enum dup_replace_mode mode);
+
+	virtual struct iterator *allocIterator() const;
+	virtual void initIterator(struct iterator *iterator,
+				  enum iterator_type type,
+				  const void *key, u32 part_count) const;
 
-+ (struct index_traits *) traits;
-+ (Index *) alloc: (struct key_def *) key_def :(struct space *) space;
+// protected:
+	/* Needed by iterators */
+	virtual size_t node_size() const = 0;
+	virtual tree_cmp_t node_cmp() const = 0;
+	virtual tree_cmp_t dup_node_cmp() const = 0;
+	virtual tree_cmp_t key_node_cmp() const= 0;
 
-/** To be defined in subclasses. */
-- (size_t) node_size;
-- (tree_cmp_t) node_cmp;
-- (tree_cmp_t) dup_node_cmp;
-- (tree_cmp_t) key_node_cmp;
-- (void) fold: (void *) node :(struct tuple *) tuple;
-- (struct tuple *) unfold: (const void *) node;
+	virtual void fold(void *node, struct tuple *tuple) const = 0;
+	virtual struct tuple *unfold(const void *node) const = 0;
 
-@end
+	sptree_index tree;
+
+protected:
+	TreeIndex(struct key_def *key_def, struct space *space);
+	virtual ~TreeIndex();
+};
 
 #endif /* TARANTOOL_BOX_TREE_INDEX_H_INCLUDED */
diff --git a/src/box/tuple.m b/src/box/tuple.cc
similarity index 92%
rename from src/box/tuple.m
rename to src/box/tuple.cc
index 4c939f0dac38adfd145dce3a8c27df18883847f4..e3e06627b70fc383350fd30788656d288935af01 100644
--- a/src/box/tuple.m
+++ b/src/box/tuple.cc
@@ -39,7 +39,7 @@ struct tuple *
 tuple_alloc(size_t size)
 {
 	size_t total = sizeof(struct tuple) + size;
-	struct tuple *tuple = salloc(total, "tuple");
+	struct tuple *tuple = (struct tuple *) salloc(total, "tuple");
 
 	tuple->flags = tuple->refs = 0;
 	tuple->bsize = size;
@@ -116,15 +116,17 @@ print_field(struct tbuf *buf, const void *f)
 		tbuf_printf(buf, "%u", *(u32 *)f);
 		break;
 	case 8:
-		tbuf_printf(buf, "%"PRIu64, *(u64 *)f);
+		tbuf_printf(buf, "%" PRIu64, *(u64 *)f);
 		break;
 	default:
 		tbuf_printf(buf, "'");
 		while (size-- > 0) {
-			if (0x20 <= *(u8 *)f && *(u8 *)f < 0x7f)
-				tbuf_printf(buf, "%c", *(u8 *)f++);
-			else
-				tbuf_printf(buf, "\\x%02X", *(u8 *)f++);
+			if (0x20 <= *(u8 *)f && *(u8 *)f < 0x7f) {
+				tbuf_printf(buf, "%c", *(u8 *) f);
+			} else {
+				tbuf_printf(buf, "\\x%02X", *(u8 *)f);
+			}
+			f = (char *) f + 1;
 		}
 		tbuf_printf(buf, "'");
 		break;
diff --git a/src/box/txn.m b/src/box/txn.cc
similarity index 96%
rename from src/box/txn.m
rename to src/box/txn.cc
index 88ad42f5c3bb8c892b64a9c437c40b37bc1564c7..cc51ab86366e4d3a6a059d767ab0588f1eae9440 100644
--- a/src/box/txn.m
+++ b/src/box/txn.cc
@@ -67,7 +67,7 @@ txn_replace(struct txn *txn, struct space *space,
 struct txn *
 txn_begin()
 {
-	struct txn *txn = p0alloc(fiber->gc_pool, sizeof(*txn));
+	struct txn *txn = (struct txn *) p0alloc(fiber->gc_pool, sizeof(*txn));
 	return txn;
 }
 
@@ -90,7 +90,7 @@ txn_commit(struct txn *txn)
 		confirm_lsn(recovery_state, lsn, res == 0);
 
 		if (res)
-			tnt_raise(LoggedError, :ER_WAL_IO);
+			tnt_raise(LoggedError, ER_WAL_IO);
 
 	}
 }
diff --git a/src/coeio.m b/src/coeio.cc
similarity index 97%
rename from src/coeio.m
rename to src/coeio.cc
index dc46539a5e806d1116418862fc56d5c32b4df480..4dac81719cac4617802b0a4ff0188bde4e553657 100644
--- a/src/coeio.m
+++ b/src/coeio.cc
@@ -129,7 +129,7 @@ struct coeio_task {
 static void
 coeio_custom_cb(eio_req *req)
 {
-	struct coeio_task *task = req->data;
+	struct coeio_task *task = (struct coeio_task *) req->data;
 	req->result = task->func(task->ap);
 }
 
@@ -148,7 +148,7 @@ coeio_on_complete(eio_req *req)
 	 * is already woken up, avoid double wake-up.
 	 */
 	if (! EIO_CANCELLED(req)) {
-		struct coeio_task *task = req->data;
+		struct coeio_task *task = (struct coeio_task *) req->data;
 		task->result = req->result;
 		task->errorno = req->errorno;
 		task->complete = 1;
@@ -221,6 +221,7 @@ getaddrinfo_cb(va_list ap)
 	struct addrinfo *hints = va_arg(ap, struct addrinfo *);
 	struct addrinfo **res = va_arg(ap, struct addrinfo **);
 
+	say_warn("Host: %s Port: %s, Hints: %p, Res: %p", host, port, hints, res);
 	int rc = getaddrinfo(host, port, hints, res);
 	/* getaddrinfo can return EAI_ADDRFAMILY on attempt
 	 * to resolve ::1, if machine has no public ipv6 addresses
diff --git a/src/coio.m b/src/coio.cc
similarity index 91%
rename from src/coio.m
rename to src/coio.cc
index 799e4c68dae12113d468b25e6bd2f5ea61552e81..a8b0ae36a74a1c5206446846a34d7de7a9112a48 100644
--- a/src/coio.m
+++ b/src/coio.cc
@@ -34,7 +34,13 @@
 #include "fiber.h"
 #include "iobuf.h"
 #include "sio.h"
+#include "scoped_guard.h"
 
+static inline void
+fiber_schedule_coio(ev_io *watcher, int event) {
+	say_warn("fiber schedule IO");
+	return fiber_schedule((ev_watcher *) watcher, event);
+}
 
 /** Note: this function does not throw */
 void
@@ -42,7 +48,7 @@ coio_init(struct ev_io *coio)
 {
 	/* Prepare for ev events. */
 	coio->data = fiber;
-	ev_init(coio, (void *) fiber_schedule);
+	ev_init(coio, fiber_schedule_coio);
 	coio->fd = -1;
 }
 
@@ -108,7 +114,7 @@ coio_connect_timeout(struct ev_io *coio, struct sockaddr_in *addr,
 		       &error, &sz);
 	if (error != 0) {
 		errno = error;
-		tnt_raise(SocketError, :coio->fd in:"connect");
+		tnt_raise(SocketError, coio->fd, "connect");
 	}
 	return false;
 }
@@ -133,26 +139,27 @@ coio_connect_addrinfo(struct ev_io *coio, struct addrinfo *ai,
 	bool res = true;
 	while (ai) {
 		struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr;
-		@try {
+		try {
 			evio_socket(coio, ai->ai_family,
 				    ai->ai_socktype,
 				    ai->ai_protocol);
 			res = coio_connect_timeout(coio, addr, ai->ai_addrlen,
 						   delay);
+			if (res)
+				evio_close(coio);
 			return res;
-		} @catch (SocketError *e) {
+		} catch (const SocketError& e) {
+			if (res)
+				evio_close(coio);
 			if (ai->ai_next == NULL)
-				@throw;
+				throw;
 			ev_now_update();
 			evio_timeout_update(start, &delay);
-		} @finally {
-			if (res)
-				evio_close(coio);
 		}
 		ai = ai->ai_next;
 	}
 	/* unreachable. */
-	tnt_raise(SocketError, :coio->fd in: "connect_addrinfo()");
+	tnt_raise(SocketError, coio->fd, "connect_addrinfo()");
 }
 
 /**
@@ -186,7 +193,7 @@ coio_accept(struct ev_io *coio, struct sockaddr_in *addr,
 		fiber_testcancel();
 		if (is_timedout) {
 			errno = ETIMEDOUT;
-			tnt_raise(SocketError, :coio->fd in:"accept");
+			tnt_raise(SocketError, coio->fd, "accept");
 		}
 		evio_timeout_update(start, &delay);
 	}
@@ -211,7 +218,12 @@ coio_read_ahead_timeout(struct ev_io *coio, void *buf, size_t sz,
 	evio_timeout_init(&start, &delay, timeout);
 
 	ssize_t to_read = (ssize_t) sz;
-	@try {
+
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
 		while (true) {
 			/*
 			 * Sic: assume the socket is ready: since
@@ -223,7 +235,7 @@ coio_read_ahead_timeout(struct ev_io *coio, void *buf, size_t sz,
 				to_read -= nrd;
 				if (to_read <= 0)
 					return sz - to_read;
-				buf += nrd;
+				buf = (char *) buf + nrd;
 				bufsiz -= nrd;
 			} else if (nrd == 0) {
 				errno = 0;
@@ -248,8 +260,6 @@ coio_read_ahead_timeout(struct ev_io *coio, void *buf, size_t sz,
 			}
 			evio_timeout_update(start, &delay);
 		}
-	} @finally {
-		ev_io_stop(coio);
 	}
 }
 
@@ -266,7 +276,7 @@ coio_readn_ahead(struct ev_io *coio, void *buf, size_t sz, size_t bufsiz)
 	ssize_t nrd = coio_read_ahead(coio, buf, sz, bufsiz);
 	if (nrd < sz) {
 		errno = EPIPE;
-		tnt_raise(SocketError, :coio->fd in:"unexpected EOF when reading "
+		tnt_raise(SocketError, coio->fd, "unexpected EOF when reading "
 			  "from socket");
 	}
 	return nrd;
@@ -286,7 +296,7 @@ coio_readn_ahead_timeout(struct ev_io *coio, void *buf, size_t sz, size_t bufsiz
 	ssize_t nrd = coio_read_ahead_timeout(coio, buf, sz, bufsiz, timeout);
 	if (nrd < sz && errno == 0) { /* EOF. */
 		errno = EPIPE;
-		tnt_raise(SocketError, :coio->fd in:"unexpected EOF when reading "
+		tnt_raise(SocketError, coio->fd, "unexpected EOF when reading "
 			  "from socket");
 	}
 	return nrd;
@@ -309,7 +319,12 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
 	size_t towrite = sz;
 	ev_tstamp start, delay;
 	evio_timeout_init(&start, &delay, timeout);
-	@try {
+
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
 		while (true) {
 			/*
 			 * Sic: write as much data as possible,
@@ -321,7 +336,7 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
 				if (nwr >= towrite)
 					return sz;
 				towrite -= nwr;
-				buf += nwr;
+				buf = (char *) buf + nwr;
 			}
 			if (! ev_is_active(coio)) {
 				ev_io_set(coio, coio->fd, EV_WRITE);
@@ -344,8 +359,6 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
 			}
 			evio_timeout_update(start, &delay);
 		}
-	} @finally {
-		ev_io_stop(coio);
 	}
 }
 
@@ -357,11 +370,13 @@ static inline ssize_t
 coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt)
 {
 	ssize_t nwr;
-	@try {
+	try {
 		sio_add_to_iov(iov, -offset);
 		nwr = sio_writev(fd, iov, iovcnt);
-	} @finally {
 		sio_add_to_iov(iov, offset);
+	} catch(const Exception& e) {
+		sio_add_to_iov(iov, offset);
+		throw;
 	}
 	return nwr;
 }
@@ -373,7 +388,12 @@ coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt,
 	ssize_t total = 0;
 	size_t iov_len = 0;
 	struct iovec *end = iov + iovcnt;
-	@try {
+
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
 		/* Avoid a syscall in case of 0 iovcnt. */
 		while (iov < end) {
 			/* Write as much data as possible. */
@@ -402,8 +422,6 @@ coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt,
 			coio_fiber_yield(coio);
 			fiber_testcancel();
 		}
-	} @finally {
-		ev_io_stop(coio);
 	}
 	return total;
 }
@@ -422,7 +440,12 @@ coio_sendto_timeout(struct ev_io *coio, const void *buf, size_t sz, int flags,
 {
 	ev_tstamp start, delay;
 	evio_timeout_init(&start, &delay, timeout);
-	@try {
+
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
 		while (true) {
 			/*
 			 * Sic: write as much data as possible,
@@ -450,8 +473,6 @@ coio_sendto_timeout(struct ev_io *coio, const void *buf, size_t sz, int flags,
 			}
 			evio_timeout_update(start, &delay);
 		}
-	} @finally {
-		ev_io_stop(coio);
 	}
 }
 
@@ -470,7 +491,11 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t sz, int flags,
 	ev_tstamp start, delay;
 	evio_timeout_init(&start, &delay, timeout);
 
-	@try {
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
 		while (true) {
 			/*
 			 * Read as much data as possible,
@@ -499,8 +524,6 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t sz, int flags,
 			}
 			evio_timeout_update(start, &delay);
 		}
-	} @finally {
-		ev_io_stop(coio);
 	}
 }
 
@@ -508,7 +531,8 @@ void
 coio_service_on_accept(struct evio_service *evio_service,
 		       int fd, struct sockaddr_in *addr)
 {
-	struct coio_service *service = evio_service->on_accept_param;
+	struct coio_service *service = (struct coio_service *)
+			evio_service->on_accept_param;
 	struct ev_io coio;
 
 	coio_init(&coio);
@@ -525,15 +549,15 @@ coio_service_on_accept(struct evio_service *evio_service,
 	struct iobuf *iobuf = NULL;
 	struct fiber *f;
 
-	@try {
+	try {
 		iobuf = iobuf_new(iobuf_name);
 		f = fiber_new(fiber_name, service->handler);
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		say_error("can't create a handler fiber, dropping client connection");
 		evio_close(&coio);
 		if (iobuf)
 			iobuf_delete(iobuf);
-		@throw;
+		throw;
 	}
 	/*
 	 * The coio is passed into the created fiber, reset the
diff --git a/src/coio_buf.m b/src/coio_buf.cc
similarity index 100%
rename from src/coio_buf.m
rename to src/coio_buf.cc
diff --git a/src/coro.m b/src/coro.cc
similarity index 94%
rename from src/coro.m
rename to src/coro.cc
index cfaf77ca5cc37351cde4a72b7bcf64d25f448f0c..e73e0267e7b64f7866d6f75889212592f8e22e46 100644
--- a/src/coro.m
+++ b/src/coro.cc
@@ -50,12 +50,12 @@ tarantool_coro_create(struct tarantool_coro *coro,
 			   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 
 	if (coro->stack == MAP_FAILED) {
-		tnt_raise(LoggedError, :ER_MEMORY_ISSUE,
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
 			  sizeof(coro->stack_size),
 			  "mmap", "coro stack");
 	}
 
-	(void) VALGRIND_STACK_REGISTER(coro->stack, coro->stack + coro->stack_size);
+	(void) VALGRIND_STACK_REGISTER(coro->stack, (char *) coro->stack + coro->stack_size);
 
 	coro_create(&coro->ctx, f, data, coro->stack, coro->stack_size);
 }
diff --git a/src/cpu_feature.m b/src/cpu_feature.c
similarity index 100%
rename from src/cpu_feature.m
rename to src/cpu_feature.c
diff --git a/src/errinj.m b/src/errinj.cc
similarity index 97%
rename from src/errinj.m
rename to src/errinj.cc
index 3f0e34c5a6ef26cc339f66c8861b37029715163a..8884c9146b896f0a28e3a78d51e067f6b826a993 100644
--- a/src/errinj.m
+++ b/src/errinj.cc
@@ -37,7 +37,7 @@
 #include "tbuf.h"
 #include "errinj.h"
 
-#define ERRINJ_MEMBER(n, s) { .name = #n, .state = s },
+#define ERRINJ_MEMBER(n, s) { /* .name = */ #n, /* .state = */ s },
 
 struct errinj errinjs[errinj_enum_MAX] = {
 	ERRINJ_LIST(ERRINJ_MEMBER)
diff --git a/src/evio.m b/src/evio.cc
similarity index 95%
rename from src/evio.m
rename to src/evio.cc
index c50880b0c7e2d38c46fc6cd5205af9e3585631ab..1d27ac18fc897b161507ddb27268af8e89252add 100644
--- a/src/evio.m
+++ b/src/evio.cc
@@ -146,7 +146,7 @@ evio_bind_addrinfo(struct ev_io *evio, struct addrinfo *ai)
 	int fd = -1;
 	while (ai) {
 		struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr;
-		@try {
+		try {
 			fd = sio_socket(ai->ai_family, ai->ai_socktype,
 					ai->ai_protocol);
 			evio_setsockopt_tcpserver(fd);
@@ -155,16 +155,16 @@ evio_bind_addrinfo(struct ev_io *evio, struct addrinfo *ai)
 				return; /* success. */
 			}
 			assert(errno == EADDRINUSE);
-		} @catch (SocketError *e) {
+		} catch (const SocketError& e) {
 			if (ai->ai_next == NULL) {
 				close(fd);
-				@throw;
+				throw;
 			}
 		}
 		close(fd);
 		ai = ai->ai_next;
 	}
-	tnt_raise(SocketError, :evio->fd in:"evio_bind_addrinfo()");
+	tnt_raise(SocketError, evio->fd, "evio_bind_addrinfo()");
 }
 
 static inline int
@@ -182,10 +182,10 @@ static void
 evio_service_accept_cb(ev_io *watcher,
 		       int revents __attribute__((unused)))
 {
-	struct evio_service *service = watcher->data;
+	struct evio_service *service = (struct evio_service *) watcher->data;
 	int fd = -1;
 
-	@try {
+	try {
 		struct sockaddr_in addr;
 		socklen_t addrlen = sizeof(addr);
 		fd = sio_accept(service->ev.fd, &addr, &addrlen);
@@ -200,10 +200,10 @@ evio_service_accept_cb(ev_io *watcher,
 		 */
 		service->on_accept(service, fd, &addr);
 
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		if (fd >= 0)
 			close(fd);
-		[e log];
+		e.log();
 	}
 }
 
@@ -219,7 +219,7 @@ evio_service_bind_and_listen(struct evio_service *service)
 	/* Create a socket. */
 	int fd = sio_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
-	@try {
+	try {
 		evio_setsockopt_tcpserver(fd);
 
 		if (sio_bind(fd, &service->addr, sizeof(service->addr)) ||
@@ -234,9 +234,9 @@ evio_service_bind_and_listen(struct evio_service *service)
 		if (service->on_bind)
 			service->on_bind(service->on_bind_param);
 
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		close(fd);
-		@throw;
+		throw;
 	}
 	/* Register the socket in the event loop. */
 	ev_io_set(&service->ev, fd, EV_READ);
@@ -252,7 +252,7 @@ evio_service_bind_and_listen(struct evio_service *service)
 static void
 evio_service_timer_cb(ev_timer *watcher, int revents __attribute__((unused)))
 {
-	struct evio_service *service = watcher->data;
+	struct evio_service *service = (struct evio_service *) watcher->data;
 	assert(! ev_is_active(&service->ev));
 
 	if (evio_service_bind_and_listen(service) == 0)
@@ -274,7 +274,7 @@ evio_service_init(struct evio_service *service, const char *name,
 	if (strcmp(host, "INADDR_ANY") == 0) {
 		service->addr.sin_addr.s_addr = INADDR_ANY;
 	} else if (inet_aton(host, &service->addr.sin_addr) == 0) {
-		tnt_raise(SocketError, :"invalid address for bind: %s",
+		tnt_raise(SocketError, -1, "invalid address for bind: %s",
 			  host);
 	}
 	service->on_accept = on_accept;
diff --git a/src/exception.cc b/src/exception.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2a92a1c5db16c9f36259c14ac134af99e6e7a1ba
--- /dev/null
+++ b/src/exception.cc
@@ -0,0 +1,117 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "exception.h"
+#include "say.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+Exception::Exception(const char *file, unsigned line)
+	: m_file(file), m_line(line)
+{
+	m_errmsg[0] = 0;
+}
+
+Exception::Exception(const Exception& e)
+	: Object(e), m_file(e.m_file), m_line(e.m_line)
+{
+	memcpy(m_errmsg, e.m_errmsg, sizeof(m_errmsg));
+}
+
+SystemError::SystemError(const char *file, unsigned line)
+	: Exception(file, line),
+	  m_errnum(errno)
+{
+	/* nothing */
+}
+
+void
+SystemError::init(const char *format, ...)
+{
+	va_list ap;
+	va_start(ap, format);
+	init(format, ap);
+	va_end(ap);
+}
+
+void
+SystemError::init(const char *format, va_list ap)
+{
+	vsnprintf(m_errmsg, sizeof(m_errmsg), format, ap);
+}
+
+void
+SystemError::log() const
+{
+	say(S_ERROR, strerror(m_errnum), "%s in %s", "SystemError",
+	    m_errmsg);
+}
+
+ClientError::ClientError(const char *file, unsigned line, uint32_t errcode, ...)
+	: Exception(file, line)
+{
+	m_errcode = errcode;
+	va_list ap;
+	va_start(ap, errcode);
+	vsnprintf(m_errmsg, sizeof(m_errmsg) - 1,
+		  tnt_errcode_desc(m_errcode), ap);
+	m_errmsg[sizeof(m_errmsg) - 1] = 0;
+	va_end(ap);
+}
+
+ClientError::ClientError(const char *file, unsigned line, const char *msg,
+			 uint32_t errcode)
+	: Exception(file, line)
+{
+	m_errcode = errcode;
+	strncpy(m_errmsg, msg, sizeof(m_errmsg) - 1);
+	m_errmsg[sizeof(m_errmsg) - 1] = 0;
+}
+
+void
+ClientError::log() const
+{
+	say_error("%s at %s:%d, %s", "ClientError",
+		  m_file, m_line, m_errmsg);
+}
+
+IllegalParams::IllegalParams(const char *file, unsigned line, const char *msg)
+	: LoggedError(file, line, ER_ILLEGAL_PARAMS, msg)
+{
+	/* nothing */
+}
+
+
+ErrorInjection::ErrorInjection(const char *file, unsigned line, const char *msg)
+	: LoggedError(file, line, ER_INJECTION, msg)
+{
+	/* nothing */
+}
+
diff --git a/src/exception.m b/src/exception.m
deleted file mode 100644
index a09b6d39037a4938ca9404bf445534a80c2a1a06..0000000000000000000000000000000000000000
--- a/src/exception.m
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "exception.h"
-#include "say.h"
-
-#include <stdio.h>
-#include <string.h>
-
-
-@implementation tnt_Exception
-+ (id) alloc
-{
-	static __thread tnt_Exception *e = nil;
-	static __thread size_t sz = 0;
-
-	if (e != nil && class_getInstanceSize(self) <= sz) {
-		object_setClass(e, self);
-	} else {
-		if (e != nil)
-			object_dispose(e);
-		e = class_createInstance(self, 0);
-		sz = class_getInstanceSize(self);
-	}
-	return e;
-}
-
-- (void) log
-{
-	[self subclassResponsibility: _cmd];
-}
-
-- (const char *) errmsg
-{
-	[self subclassResponsibility: _cmd];
-	return  NULL;
-}
-@end
-
-@implementation SystemError
-
-- (id) init: (const char *) format, ...
-{
-	va_list ap;
-	va_start(ap, format);
-	self = [self init: errno :format :ap];
-	va_end(ap);
-	return self;
-}
-
-- (id) init: (int)errnum_arg :(const char *)format :(va_list)ap
-{
-	self = [super init];
-	errnum = errnum_arg;
-	vsnprintf(errmsg, sizeof(errmsg), format, ap);
-	return self;
-}
-
-- (void) log
-{
-	say(S_ERROR, strerror(errnum), "%s in %s", object_getClassName(self), errmsg);
-}
-
-- (const char *) errmsg
-{
-	return errmsg;
-}
-@end
-
-
-@implementation ClientError
-- (id) init: (uint32_t)errcode_, ...
-{
-	va_list ap;
-	va_start(ap, errcode_);
-	[self init: errcode_ args: ap];
-	va_end(ap);
-
-	return self;
-}
-
-
-- (id) init: (uint32_t)errcode_ args :(va_list)ap
-{
-	[super init];
-	errcode = errcode_;
-	vsnprintf(errmsg, sizeof(errmsg), tnt_errcode_desc(errcode), ap);
-	return self;
-}
-
-- (id) init: (uint32_t)errcode_ :(const char *)msg
-{
-	[super init];
-	errcode = errcode_;
-	snprintf(errmsg, sizeof(errmsg), "%s", msg);
-	return self;
-}
-
-- (void) log
-{
-	say_error("%s at %s:%d, %s", object_getClassName(self),
-		  file, line, errmsg);
-}
-
-- (const char *) errmsg
-{
-	return errmsg;
-}
-@end
-
-
-@implementation LoggedError
-- (id) init: (uint32_t) errcode_, ...
-{
-	va_list ap;
-	va_start(ap, errcode_);
-	[super init: errcode_ args: ap];
-
-	[self log];
-
-	return self;
-}
-@end
-
-
-@implementation IllegalParams
-- (id) init: (const char*) msg
-{
-	return [super init: ER_ILLEGAL_PARAMS, msg];
-}
-@end
-
-@implementation ErrorInjection
-- (id) init: (const char*) msg
-{
-	return [super init: ER_INJECTION, msg];
-}
-@end
diff --git a/src/fiber.m b/src/fiber.cc
similarity index 89%
rename from src/fiber.m
rename to src/fiber.cc
index 4066cd910bb4404762b3056cd84619030de03612..8894a8b7ec0c2878256c0f01bf21962b863aeb56 100644
--- a/src/fiber.m
+++ b/src/fiber.cc
@@ -35,17 +35,16 @@
 
 #include <say.h>
 #include <tarantool.h>
-#include TARANTOOL_CONFIG
+extern "C" {
+#include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 #include <tbuf.h>
 #include <stat.h>
 #include <assoc.h>
 #include "iobuf.h"
 #include <rlist.h>
 
-@implementation FiberCancelException
-@end
-
-
 enum { FIBER_CALL_STACK = 16 };
 
 static struct fiber sched;
@@ -221,11 +220,19 @@ fiber_yield(void)
 }
 
 
+struct fiber_watcher_data {
+	struct fiber *f;
+	bool timed_out;
+};
+
 static void
-fiber_schedule_timeout(ev_watcher *watcher)
+fiber_schedule_timeout(ev_timer *watcher, int revents)
 {
+	(void) revents;
+
 	assert(fiber == &sched);
-	struct { struct fiber *f; bool timed_out; } *state = watcher->data;
+	struct fiber_watcher_data *state =
+			(struct fiber_watcher_data *) watcher->data;
 	state->timed_out = true;
 	fiber_call(state->f);
 }
@@ -238,8 +245,8 @@ bool
 fiber_yield_timeout(ev_tstamp delay)
 {
 	struct ev_timer timer;
-	ev_timer_init(&timer, (void *)fiber_schedule_timeout, delay, 0);
-	struct { struct fiber *f; bool timed_out; } state = { fiber, false };
+	ev_timer_init(&timer, fiber_schedule_timeout, delay, 0);
+	struct fiber_watcher_data state = { fiber, false };
 	timer.data = &state;
 	ev_timer_start(&timer);
 	fiber_yield();
@@ -270,11 +277,17 @@ fiber_sleep(ev_tstamp delay)
  * @note: this is a cancellation point (@sa fiber_testcancel()).
  * @return process return status
 */
+void
+fiber_schedule_child(ev_child *watcher, int event __attribute__((unused)))
+{
+	return fiber_schedule((ev_watcher *) watcher, event);
+}
+
 int
 wait_for_child(pid_t pid)
 {
 	ev_child cw;
-	ev_init(&cw, (void *)fiber_schedule);
+	ev_init(&cw, fiber_schedule_child);
 	ev_child_set(&cw, pid, 0);
 	cw.data = fiber;
 	ev_child_start(&cw);
@@ -289,12 +302,15 @@ void
 fiber_schedule(ev_watcher *watcher, int event __attribute__((unused)))
 {
 	assert(fiber == &sched);
-	fiber_call(watcher->data);
+	fiber_call((struct fiber *) watcher->data);
 }
 
 static void
-fiber_ready_async(void)
+fiber_ready_async(ev_async *watcher, int revents)
 {
+	(void) watcher;
+	(void) revents;
+
 	while(!rlist_empty(&ready_fibers)) {
 		struct fiber *f =
 			rlist_first_entry(&ready_fibers, struct fiber, state);
@@ -304,27 +320,27 @@ fiber_ready_async(void)
 }
 
 struct fiber *
-fiber_find(int fid)
+fiber_find(uint32_t fid)
 {
-	struct mh_i32ptr_node_t node = { .key = fid };
+	struct mh_i32ptr_node_t node = { fid, NULL };
 	mh_int_t k = mh_i32ptr_get(fiber_registry, &node, NULL);
 
 	if (k == mh_end(fiber_registry))
 		return NULL;
-	return mh_i32ptr_node(fiber_registry, k)->val;
+	return (struct fiber *) mh_i32ptr_node(fiber_registry, k)->val;
 }
 
 static void
 register_fid(struct fiber *fiber)
 {
-	struct mh_i32ptr_node_t node = { .key = fiber -> fid, .val = fiber };
+	struct mh_i32ptr_node_t node = { fiber -> fid, fiber };
 	mh_i32ptr_put(fiber_registry, &node, NULL, NULL);
 }
 
 static void
 unregister_fid(struct fiber *fiber)
 {
-	struct mh_i32ptr_node_t node = { .key = fiber->fid };
+	struct mh_i32ptr_node_t node = { fiber->fid, NULL };
 	mh_i32ptr_remove(fiber_registry, &node, NULL);
 }
 
@@ -364,16 +380,17 @@ fiber_loop(void *data __attribute__((unused)))
 {
 	for (;;) {
 		assert(fiber != NULL && fiber->f != NULL && fiber->fid != 0);
-		@try {
+		try {
 			fiber->f(fiber->f_data);
-		} @catch (FiberCancelException *e) {
+		} catch (const FiberCancelException& e) {
 			say_info("fiber `%s' has been cancelled", fiber_name(fiber));
 			say_info("fiber `%s': exiting", fiber_name(fiber));
-		} @catch (tnt_Exception *e) {
-			[e log];
-		} @catch (id e) {
-			say_error("fiber `%s': exception `%s'",
-				fiber_name(fiber), object_getClassName(e));
+		} catch (const Exception& e) {
+			e.log();
+		} catch (...) {
+			/* TODO: this case should never happen */
+			say_error("fiber `%s': unknown exception",
+				fiber_name(fiber));
 			panic("fiber `%s': exiting", fiber_name(fiber));
 		}
 		fiber_zombificate();
@@ -414,7 +431,7 @@ fiber_new(const char *name, void (*f) (va_list))
 		fiber = rlist_first_entry(&zombie_fibers, struct fiber, link);
 		rlist_move_entry(&fibers, fiber, link);
 	} else {
-		fiber = palloc(eter_pool, sizeof(*fiber));
+		fiber = (struct fiber *) palloc(eter_pool, sizeof(*fiber));
 
 		memset(fiber, 0, sizeof(*fiber));
 		tarantool_coro_create(&fiber->coro, fiber_loop, NULL);
@@ -474,7 +491,7 @@ fiber_destroy_all()
 static void
 fiber_info_print(struct tbuf *out, struct fiber *fiber)
 {
-	void *stack_top = fiber->coro.stack + fiber->coro.stack_size;
+	void *stack_top = (char *) fiber->coro.stack + fiber->coro.stack_size;
 
 	tbuf_printf(out, "  - fid: %4i" CRLF, fiber->fid);
 	tbuf_printf(out, "    csw: %i" CRLF, fiber->csw);
@@ -519,7 +536,7 @@ fiber_init(void)
 
 	iobuf_init_readahead(cfg.readahead);
 
-	ev_async_init(&ready_async, (void *)fiber_ready_async);
+	ev_async_init(&ready_async, fiber_ready_async);
 	ev_async_start(&ready_async);
 }
 
diff --git a/src/iobuf.m b/src/iobuf.cc
similarity index 95%
rename from src/iobuf.m
rename to src/iobuf.cc
index fbf8b696892500fb271a04004d0f3710f6734968..56ff2ea1e22c7968d3690cc9b0a8a9eb6dab606f 100644
--- a/src/iobuf.m
+++ b/src/iobuf.cc
@@ -73,7 +73,7 @@ ibuf_reserve(struct ibuf *ibuf, size_t size)
 		while (new_capacity < current_size + size)
 			new_capacity *= 2;
 
-		ibuf->buf = palloc(ibuf->pool, new_capacity);
+		ibuf->buf = (char *) palloc(ibuf->pool, new_capacity);
 		memcpy(ibuf->buf, ibuf->pos, current_size);
 		ibuf->capacity = new_capacity;
 	}
@@ -93,7 +93,7 @@ static inline void
 obuf_init_pos(struct obuf *buf, size_t pos)
 {
 	if (pos >= IOBUF_IOV_MAX) {
-		tnt_raise(LoggedError, :ER_MEMORY_ISSUE, buf->pos,
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE, buf->pos,
 			  "obuf_init_pos", "iovec");
 	}
 	buf->iov[pos].iov_base = NULL;
@@ -165,11 +165,11 @@ obuf_dup(struct obuf *buf, const void *data, size_t size)
 			 */
 			size_t fill = capacity - iov->iov_len;
 			assert(fill < size);
-			memcpy(iov->iov_base + iov->iov_len, data, fill);
+			memcpy((char *) iov->iov_base + iov->iov_len, data, fill);
 
 			iov->iov_len += fill;
 			buf->size += fill;
-			data += fill;
+			data = (char *) data + fill;
 			size -= fill;
 			/*
 			 * Check if the remainder can fit
@@ -193,7 +193,7 @@ obuf_dup(struct obuf *buf, const void *data, size_t size)
 		iov = &buf->iov[buf->pos];
 		capacity = buf->capacity[buf->pos];
 	}
-	memcpy(iov->iov_base + iov->iov_len, data, size);
+	memcpy((char *) iov->iov_base + iov->iov_len, data, size);
 	iov->iov_len += size;
 	buf->size += size;
 	assert(iov->iov_len <= buf->capacity[buf->pos]);
@@ -221,9 +221,11 @@ obuf_book(struct obuf *buf, size_t size)
 			obuf_alloc_pos(buf, buf->pos, size);
 		}
 	}
-	struct obuf_svp svp = {
-		.pos = buf->pos, .iov_len = iov->iov_len, .size = buf->size
-	};
+	struct obuf_svp svp;
+	svp.pos = buf->pos;
+	svp.iov_len = iov->iov_len;
+	svp.size = buf->size;
+
 	iov->iov_len += size;
 	buf->size += size;
 	assert(iov->iov_len <= buf->capacity[buf->pos]);
@@ -272,7 +274,7 @@ iobuf_new(const char *name)
 {
 	struct iobuf *iobuf;
 	if (SLIST_EMPTY(&iobuf_cache)) {
-		iobuf = palloc(eter_pool, sizeof(struct iobuf));
+		iobuf = (struct iobuf *) palloc(eter_pool, sizeof(struct iobuf));
 		struct palloc_pool *pool = palloc_create_pool("");
 		/* Note: do not allocate memory upfront. */
 		ibuf_create(&iobuf->in, pool);
diff --git a/src/ipc.m b/src/ipc.cc
similarity index 99%
rename from src/ipc.m
rename to src/ipc.cc
index 9274abdd1316aacd530b55859965687f815f5c37..41832a2bac435091c184bfecb21304799d854fc3 100644
--- a/src/ipc.m
+++ b/src/ipc.cc
@@ -63,7 +63,7 @@ ipc_channel_new(unsigned size)
 {
 	if (!size)
 		size = 1;
-	struct ipc_channel *res =
+	struct ipc_channel *res = (struct ipc_channel *)
 		malloc(sizeof(struct ipc_channel) + sizeof(void *) * size);
 	if (res == NULL)
 		return NULL;
diff --git a/src/iproto.m b/src/iproto.cc
similarity index 91%
rename from src/iproto.m
rename to src/iproto.cc
index c50a391f7d40acd1829564295a32a7c751dabf8f..86249b440d13029caa41c523834ba89b9a024da1 100644
--- a/src/iproto.m
+++ b/src/iproto.cc
@@ -44,6 +44,7 @@
 #include "iobuf.h"
 #include "evio.h"
 #include "session.h"
+#include "scoped_guard.h"
 
 enum {
 	/** Maximal iproto package body length (2GiB) */
@@ -193,7 +194,7 @@ struct iproto_queue
 	/**
 	 * Cache of fibers which work on requests
 	 * in this queue.
-         */
+	 */
 	struct rlist fiber_cache;
 	/**
 	 * Used to trigger request processing when
@@ -301,7 +302,7 @@ static void
 iproto_queue_schedule(struct ev_async *watcher,
 		      int events __attribute__((unused)))
 {
-	struct iproto_queue *i_queue = watcher->data;
+	struct iproto_queue *i_queue = (struct iproto_queue *) watcher->data;
 	while (! iproto_queue_is_empty(i_queue)) {
 
 		struct fiber *f = rlist_shift_entry(&i_queue->fiber_cache,
@@ -318,7 +319,7 @@ iproto_queue_init(struct iproto_queue *i_queue,
 {
 	i_queue->size = size;
 	i_queue->begin = i_queue->end = 0;
-	i_queue->queue = palloc(eter_pool, size *
+	i_queue->queue = (struct iproto_request *) palloc(eter_pool, size *
 				sizeof (struct iproto_request));
 	/**
 	 * Initialize an ev_async event which would start
@@ -376,7 +377,7 @@ struct iproto_session
 	 * relative to in->end, rather than to in->pos is helpful to
 	 * make sure ibuf_reserve() or iobuf rotation don't make
 	 * the value meaningless.
-         */
+	 */
 	ssize_t parse_size;
 	/** Current write position in the output buffer */
 	struct obuf_svp write_pos;
@@ -438,7 +439,7 @@ iproto_session_create(const char *name, int fd, box_process_func *param)
 {
 	struct iproto_session *session;
 	if (SLIST_EMPTY(&iproto_session_cache)) {
-		session = palloc(eter_pool, sizeof(*session));
+		session = (struct iproto_session *) palloc(eter_pool, sizeof(*session));
 		session->input.data = session->output.data = session;
 	} else {
 		session = SLIST_FIRST(&iproto_session_cache);
@@ -488,7 +489,7 @@ iproto_session_shutdown(struct iproto_session *session)
 	 * trigger and destroy the session.
 	 * Sic: the check is mandatory to not destroy a session
 	 * twice.
-         */
+	 */
 	if (iproto_session_is_idle(session)) {
 		iproto_enqueue_request(&request_queue, session,
 				       session->iobuf[0], &dummy_header,
@@ -499,14 +500,13 @@ iproto_session_shutdown(struct iproto_session *session)
 static inline void
 iproto_validate_header(struct iproto_header *header, int fd)
 {
+	(void) fd;
 	if (header->len > IPROTO_BODY_LEN_MAX) {
 		/*
 		 * The package is too big, just close connection for now to
 		 * avoid DoS.
 		 */
-		tnt_raise(SocketError, :fd in:
-			  "received package is too big: %llu",
-			  (unsigned long long) header->len);
+		tnt_raise(IllegalParams, "received package is too big");
 	}
 }
 
@@ -536,20 +536,20 @@ iproto_validate_header(struct iproto_header *header, int fd)
 static struct iobuf *
 iproto_session_input_iobuf(struct iproto_session *session)
 {
-	struct iobuf *old = session->iobuf[0];
+	struct iobuf *oldbuf = session->iobuf[0];
 
 	ssize_t to_read = sizeof(struct iproto_header) +
 		(session->parse_size >= sizeof(struct iproto_header) ?
-		iproto(old->in.end - session->parse_size)->len : 0) -
+		iproto(oldbuf->in.end - session->parse_size)->len : 0) -
 		session->parse_size;
 
-	if (ibuf_unused(&old->in) >= to_read)
-		return old;
+	if (ibuf_unused(&oldbuf->in) >= to_read)
+		return oldbuf;
 
 	/** All requests are processed, reuse the buffer. */
-	if (ibuf_size(&old->in) == session->parse_size) {
-		ibuf_reserve(&old->in, to_read);
-		return old;
+	if (ibuf_size(&oldbuf->in) == session->parse_size) {
+		ibuf_reserve(&oldbuf->in, to_read);
+		return oldbuf;
 	}
 
 	if (! iobuf_is_idle(session->iobuf[1])) {
@@ -559,24 +559,24 @@ iproto_session_input_iobuf(struct iproto_session *session)
 		 */
 		return NULL;
 	}
-	struct iobuf *new = session->iobuf[1];
+	struct iobuf *newbuf = session->iobuf[1];
 
-	ibuf_reserve(&new->in, to_read + session->parse_size);
+	ibuf_reserve(&newbuf->in, to_read + session->parse_size);
 	/*
 	 * Discard unparsed data in the old buffer, otherwise it
 	 * won't be recycled when all parsed requests are processed.
 	 */
-	old->in.end -= session->parse_size;
+	oldbuf->in.end -= session->parse_size;
 	/* Move the cached request prefix to the new buffer. */
-	memcpy(new->in.pos, old->in.end, session->parse_size);
-	new->in.end += session->parse_size;
+	memcpy(newbuf->in.pos, oldbuf->in.end, session->parse_size);
+	newbuf->in.end += session->parse_size;
 	/*
 	 * Rotate buffers. Not strictly necessary, but
 	 * helps preserve response order.
 	 */
-	session->iobuf[1] = old;
-	session->iobuf[0] = new;
-	return new;
+	session->iobuf[1] = oldbuf;
+	session->iobuf[0] = newbuf;
+	return newbuf;
 }
 
 /** Enqueue all requests which were read up. */
@@ -608,11 +608,11 @@ static void
 iproto_session_on_input(struct ev_io *watcher,
 			int revents __attribute__((unused)))
 {
-	struct iproto_session *session = watcher->data;
+	struct iproto_session *session = (struct iproto_session *) watcher->data;
 	int fd = session->input.fd;
 	assert(fd >= 0);
 
-	@try {
+	try {
 		/* Ensure we have sufficient space for the next round.  */
 		struct iobuf *iobuf = iproto_session_input_iobuf(session);
 		if (iobuf == NULL) {
@@ -642,8 +642,8 @@ iproto_session_on_input(struct ev_io *watcher,
 		 */
 		if (!ev_is_active(&session->input))
 			ev_feed_event(&session->input, EV_READ);
-	} @catch (tnt_Exception *e) {
-		[e log];
+	} catch (const Exception& e) {
+		e.log();
 		iproto_session_shutdown(session);
 	}
 }
@@ -675,12 +675,16 @@ iproto_flush(struct iobuf *iobuf, int fd, struct obuf_svp *svp)
 	int iovcnt = obuf_iovcnt(&iobuf->out) - svp->pos;
 	assert(iovcnt);
 	ssize_t nwr;
-	@try {
+	try {
 		sio_add_to_iov(iov, -svp->iov_len);
 		nwr = sio_writev(fd, iov, iovcnt);
-	} @finally {
+
+		sio_add_to_iov(iov, svp->iov_len);
+	} catch(const Exception&) {
 		sio_add_to_iov(iov, svp->iov_len);
+		throw;
 	}
+
 	if (nwr > 0) {
 		if (svp->size + nwr == obuf_size(&iobuf->out)) {
 			iobuf_gc(iobuf);
@@ -697,11 +701,11 @@ static void
 iproto_session_on_output(struct ev_io *watcher,
 			 int revent __attribute__((unused)))
 {
-	struct iproto_session *session = watcher->data;
+	struct iproto_session *session = (struct iproto_session *) watcher->data;
 	int fd = session->output.fd;
 	struct obuf_svp *svp = &session->write_pos;
 
-	@try {
+	try {
 		struct iobuf *iobuf;
 		while ((iobuf = iproto_session_output_iobuf(session))) {
 			if (iproto_flush(iobuf, fd, svp) < 0) {
@@ -713,8 +717,8 @@ iproto_session_on_output(struct ev_io *watcher,
 		}
 		if (ev_is_active(&session->output))
 			ev_io_stop(&session->output);
-	} @catch (tnt_Exception *e) {
-		[e log];
+	} catch (const Exception& e) {
+		e.log();
 		iproto_session_shutdown(session);
 	}
 }
@@ -735,15 +739,15 @@ iproto_reply_ping(struct obuf *out, struct iproto_header *req)
 /** Send an error packet back. */
 static inline void
 iproto_reply_error(struct obuf *out, struct iproto_header *req,
-		   ClientError *e)
+		   const ClientError& e)
 {
 	struct iproto_header reply = *req;
-	int errmsg_len = strlen(e->errmsg) + 1;
-	uint32_t ret_code = tnt_errcode_val(e->errcode);
+	int errmsg_len = strlen(e.errmsg()) + 1;
+	uint32_t ret_code = tnt_errcode_val(e.errcode());
 	reply.len = sizeof(ret_code) + errmsg_len;;
 	obuf_dup(out, &reply, sizeof(reply));
 	obuf_dup(out, &ret_code, sizeof(ret_code));
-	obuf_dup(out, e->errmsg, errmsg_len);
+	obuf_dup(out, e.errmsg(), errmsg_len);
 }
 
 /** Stack a reply to a single request to the fiber's io vector. */
@@ -757,10 +761,10 @@ iproto_reply(struct port_iproto *port, box_process_func callback,
 	/* Make request body point to iproto data */
 	void *body = (char *) &header[1];
 	port_iproto_init(port, out, header);
-	@try {
+	try {
 		callback((struct port *) port, header->msg_code,
 			 body, header->len);
-	} @catch (ClientError *e) {
+	} catch (const ClientError& e) {
 		if (port->reply.found)
 			obuf_rollback_to_svp(out, &port->svp);
 		iproto_reply_error(out, header, e);
@@ -774,22 +778,23 @@ iproto_process_request(struct iproto_request *request)
 	struct iproto_header *header = request->header;
 	struct iobuf *iobuf = request->iobuf;
 	struct port_iproto port;
-	@try {
-		if (unlikely(! evio_is_active(&session->output)))
-			return;
 
-		iproto_reply(&port, *session->handler,
-			     &iobuf->out, header);
-
-		if (unlikely(! evio_is_active(&session->output)))
-			return;
-		if (! ev_is_active(&session->output))
-			ev_feed_event(&session->output, EV_WRITE);
-	} @finally {
+	auto scope_guard = make_scoped_guard([=]{
 		iobuf->in.pos += sizeof(*header) + header->len;
 		if (iproto_session_is_idle(session))
 			iproto_session_destroy(session);
-	}
+	});
+
+	if (unlikely(! evio_is_active(&session->output)))
+		return;
+
+	iproto_reply(&port, *session->handler, &iobuf->out, header);
+
+	if (unlikely(! evio_is_active(&session->output)))
+		return;
+
+	if (! ev_is_active(&session->output))
+		ev_feed_event(&session->output, EV_WRITE);
 }
 
 /**
@@ -803,19 +808,19 @@ iproto_process_connect(struct iproto_request *request)
 	struct iproto_session *session = request->session;
 	struct iobuf *iobuf = request->iobuf;
 	int fd = session->input.fd;
-	@try {              /* connect. */
+	try {              /* connect. */
 		session->sid = session_create(fd);
-	} @catch (ClientError *e) {
+	} catch (const ClientError& e) {
 		iproto_reply_error(&iobuf->out, request->header, e);
-		@try {
+		try {
 			iproto_flush(iobuf, fd, &session->write_pos);
-		} @catch (tnt_Exception *e) {
-			[e log];
+		} catch (const Exception& e) {
+			e.log();
 		}
 		iproto_session_shutdown(session);
 		return;
-	} @catch (tnt_Exception *e) {
-		[e log];
+	} catch (const Exception& e) {
+		e.log();
 		assert(session->sid == 0);
 		iproto_session_shutdown(session);
 		return;
@@ -852,7 +857,10 @@ iproto_on_accept(struct evio_service *service, int fd,
 	snprintf(name, sizeof(name), "%s/%s", "iobuf", sio_strfaddr(addr));
 
 	struct iproto_session *session;
-	session = iproto_session_create(name, fd, service->on_accept_param);
+
+	box_process_func *process_fun = reinterpret_cast<box_process_func*>(
+				service->on_accept_param);
+	session = iproto_session_create(name, fd, process_fun);
 	iproto_enqueue_request(&request_queue, session,
 			       session->iobuf[0], &dummy_header,
 			       iproto_process_connect);
diff --git a/src/lib/bit/CMakeLists.txt b/src/lib/bit/CMakeLists.txt
index c1728e1634e2783876d0f6a4bf97245d7037246e..d30afe221644298f458de3c12d1d3705675a2a25 100644
--- a/src/lib/bit/CMakeLists.txt
+++ b/src/lib/bit/CMakeLists.txt
@@ -1,27 +1,3 @@
-check_builtin_function_exists("__builtin_ctz" HAVE_BUILTIN_CTZ)
-check_builtin_function_exists("__builtin_ctzll" HAVE_BUILTIN_CTZLL)
-check_builtin_function_exists("__builtin_clz" HAVE_BUILTIN_CLZ)
-check_builtin_function_exists("__builtin_clzll" HAVE_BUILTIN_CLZLL)
-check_builtin_function_exists("__builtin_popcount" HAVE_BUILTIN_POPCOUNT)
-check_builtin_function_exists("__builtin_popcountll" HAVE_BUILTIN_POPCOUNTLL)
-check_builtin_function_exists("__builtin_bswap32" HAVE_BUILTIN_BSWAP32)
-check_builtin_function_exists("__builtin_bswap64" HAVE_BUILTIN_BSWAP64)
-
-if (NOT HAVE_BUILTIN_CTZ OR NOT HAVE_BUILTIN_CTZLL)
-    # Check if -D_GNU_SOURCE has been defined and add this flag to
-    # CMAKE_REQUIRED_DEFINITIONS in order to get check_prototype_definition work
-    get_property(var DIRECTORY PROPERTY COMPILE_DEFINITIONS)
-    list(FIND var "_GNU_SOURCE" var)
-    if (NOT var EQUAL -1)
-        set(CMAKE_REQUIRED_FLAGS "-Wno-error")
-        set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
-        check_c_source_compiles("#include <string.h>\n#include <strings.h>\nint main(void) { return ffsl(0L); }"
-            HAVE_FFSL)
-        check_c_source_compiles("#include <string.h>\n#include <strings.h>\nint main(void) { return ffsll(0UL); }"
-            HAVE_FFSLL)
-    endif()
-endif()
-
 if ((HAVE_BUILTIN_CTZ OR HAVE_FFSL) AND
     (HAVE_BUILTIN_CTZLL OR HAVE_FFSLL) AND
     HAVE_BUILTIN_CLZ AND HAVE_BUILTIN_CLZLL AND
diff --git a/src/lib/bit/bit.c b/src/lib/bit/bit.c
index f446961587f955e6464b4bfe1ac3f2d6fff764b7..c2a9b67c56495726eb31fbc649b3d0b7e819c34e 100644
--- a/src/lib/bit/bit.c
+++ b/src/lib/bit/bit.c
@@ -74,9 +74,9 @@ bswap_u32(uint32_t x);
 extern inline uint64_t
 bswap_u64(uint64_t x);
 
-#define BITINDEX_NAIVE(x, bitsize) {					\
+#define BITINDEX_NAIVE(type, x, bitsize) {				\
 	/* naive generic implementation, worst case */			\
-	typeof(x) bit = 1;						\
+	type bit = 1;							\
 	int i = 0;							\
 	for (int k = 0; k < bitsize; k++) {				\
 		if (x & bit) {						\
@@ -116,7 +116,7 @@ bit_index_u32(uint32_t x, int *indexes, int offset)
 	indexes[i] = 0;
 	return indexes + i;
 #else /* !defined(HAVE_BUILTIN_CTZ) */
-	BITINDEX_NAIVE(x, sizeof(uint32_t) * CHAR_BIT);
+	BITINDEX_NAIVE(uint32_t, x, sizeof(uint32_t) * CHAR_BIT);
 #endif
 }
 
@@ -146,7 +146,7 @@ bit_index_u64(uint64_t x, int *indexes, int offset) {
 	indexes[i] = 0;
 	return indexes + i;
 #else /* !defined(HAVE_CTZ) */
-	BITINDEX_NAIVE(x, sizeof(uint64_t) * CHAR_BIT);
+	BITINDEX_NAIVE(uint64_t, x, sizeof(uint64_t) * CHAR_BIT);
 #endif
 }
 
diff --git a/src/lib/bitset/index.c b/src/lib/bitset/index.c
index a30c27d70dd7a2acd0be8a144d091e4181dcdf54..7250dcb5208a72295a3227d26b42a07f6ebc65e8 100644
--- a/src/lib/bitset/index.c
+++ b/src/lib/bitset/index.c
@@ -388,4 +388,4 @@ bitset_index_init_iterator(struct bitset_index *index,
 }
 
 extern inline size_t
-bitset_index_size(struct bitset_index *index);
+bitset_index_size(const struct bitset_index *index);
diff --git a/src/lib/bitset/page.h b/src/lib/bitset/page.h
index 79b4bbf4ff3f7633e5d0c943fcc94853a717bf5a..4f519b30c8183db31a7c2f156f885b92f7400c6e 100644
--- a/src/lib/bitset/page.h
+++ b/src/lib/bitset/page.h
@@ -47,6 +47,10 @@
 #include <limits.h>
 #include <assert.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 enum {
 	/** How many bytes to store in one page */
 	BITSET_PAGE_DATA_SIZE = 160
@@ -187,4 +191,9 @@ bitset_page_dump(struct bitset_page *page, FILE *stream);
 
 rb_proto(, bitset_pages_, bitset_pages_t, struct bitset_page)
 
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
 #endif /* TARANTOOL_LIB_BITSET_PAGE_H_INCLUDED */
diff --git a/src/log_io.m b/src/log_io.cc
similarity index 92%
rename from src/log_io.m
rename to src/log_io.cc
index 1eb9fd89db0dc9e240e7f8cf1a0e9476392aec9f..27fb967a75590931e131bc929921c31dc29037d6 100644
--- a/src/log_io.m
+++ b/src/log_io.cc
@@ -45,9 +45,9 @@ const char v11[] = "0.11\n";
 void
 header_v11_sign(struct header_v11 *header)
 {
-	header->data_crc32c = crc32_calc(0, (void *) header + sizeof(struct
+	header->data_crc32c = crc32_calc(0, (const unsigned char *) header + sizeof(struct
 						  header_v11), header->len);
-	header->header_crc32c = crc32_calc(0, (void *) &header->lsn,
+	header->header_crc32c = crc32_calc(0, (const unsigned char *) &header->lsn,
 					   sizeof(struct header_v11) -
 					   sizeof(header->header_crc32c));
 }
@@ -66,23 +66,28 @@ row_v11_fill(struct row_v11 *row, u64 lsn, u16 tag, u64 cookie,
 			sizeof(row->tag) + sizeof(row->cookie));
 }
 
-/* {{{ struct log_dir and related functions */
-
 struct log_dir snap_dir = {
-	.filetype = "SNAP\n",
-	.filename_ext = ".snap"
+	/* .panic_if_error = */ false,
+	/* .sync_is_async = */ false,
+	/* .open_wflags = */ 0,
+	/* .filetype = */ "SNAP\n",
+	/* .filename_ext = */ ".snap",
+	/* .dirname = */ NULL
 };
 
 struct log_dir wal_dir = {
-	.sync_is_async = true,
-	.filetype = "XLOG\n",
-	.filename_ext = ".xlog"
+	/* .panic_if_error = */ false,
+	/* .sync_is_async = */ true,
+	/* .open_wflags = */ 0,
+	/* .filetype = */ "XLOG\n",
+	/* .filename_ext = */ ".xlog",
+	/* .dirname = */ NULL
 };
 
 static int
 cmp_i64(const void *_a, const void *_b)
 {
-	const i64 *a = _a, *b = _b;
+	const i64 *a = (const i64 *) _a, *b = (const i64 *) _b;
 	if (*a == *b)
 		return 0;
 	return (*a > *b) ? 1 : -1;
@@ -94,7 +99,7 @@ scan_dir(struct log_dir *dir, i64 **ret_lsn)
 	ssize_t result = -1;
 	size_t i = 0, size = 1024;
 	ssize_t ext_len = strlen(dir->filename_ext);
-	i64 *lsn = palloc(fiber->gc_pool, sizeof(i64) * size);
+	i64 *lsn = (i64 *) palloc(fiber->gc_pool, sizeof(i64) * size);
 	DIR *dh = opendir(dir->dirname);
 
 	if (lsn == NULL || dh == NULL)
@@ -138,7 +143,7 @@ scan_dir(struct log_dir *dir, i64 **ret_lsn)
 
 		i++;
 		if (i == size) {
-			i64 *n = palloc(fiber->gc_pool, sizeof(i64) * size * 2);
+			i64 *n = (i64 *) palloc(fiber->gc_pool, sizeof(i64) * size * 2);
 			if (n == NULL)
 				goto out;
 			memcpy(n, lsn, sizeof(i64) * size);
@@ -214,7 +219,8 @@ format_filename(struct log_dir *dir, i64 lsn, enum log_suffix suffix)
 
 /* {{{ struct log_io_cursor */
 
-#define ROW_EOF (void *)1
+/* TODO: wtf? */
+#define ROW_EOF (struct tbuf *) 1
 
 static struct tbuf *
 row_reader_v11(FILE *f, struct palloc_pool *pool)
@@ -230,7 +236,7 @@ row_reader_v11(FILE *f, struct palloc_pool *pool)
 	m->size = sizeof(struct header_v11);
 
 	/* header crc32c calculated on <lsn, tm, len, data_crc32c> */
-	header_crc = crc32_calc(0, m->data + offsetof(struct header_v11, lsn),
+	header_crc = crc32_calc(0, (const unsigned char *) m->data + offsetof(struct header_v11, lsn),
 				sizeof(struct header_v11) - offsetof(struct header_v11, lsn));
 
 	if (header_v11(m)->header_crc32c != header_crc) {
@@ -244,7 +250,7 @@ row_reader_v11(FILE *f, struct palloc_pool *pool)
 
 	m->size += header_v11(m)->len;
 
-	data_crc = crc32_calc(0, m->data + sizeof(struct header_v11), header_v11(m)->len);
+	data_crc = crc32_calc(0, (const unsigned char *) m->data + sizeof(struct header_v11), header_v11(m)->len);
 	if (header_v11(m)->data_crc32c != data_crc) {
 		say_error("data crc32c mismatch");
 		return NULL;
@@ -289,6 +295,7 @@ struct tbuf *
 log_io_cursor_next(struct log_io_cursor *i)
 {
 	struct log_io *l = i->log;
+	struct tbuf *row;
 	log_magic_t magic;
 	off_t marker_offset = 0;
 
@@ -327,7 +334,7 @@ log_io_cursor_next(struct log_io_cursor *i)
 			(uintmax_t)i->good_offset);
 	say_debug("magic found at 0x%08jx", (uintmax_t)marker_offset);
 
-	struct tbuf *row = row_reader_v11(l->f, fiber->gc_pool);
+	row = row_reader_v11(l->f, fiber->gc_pool);
 	if (row == ROW_EOF)
 		goto eof;
 
@@ -393,7 +400,7 @@ inprogress_log_rename(struct log_io *l)
 	assert(strcmp(suffix, inprogress_suffix) == 0);
 
 	/* Create a new filename without '.inprogress' suffix. */
-	new_filename = alloca(suffix - filename + 1);
+	new_filename = (char *) alloca(suffix - filename + 1);
 	memcpy(new_filename, filename, suffix - filename);
 	new_filename[suffix - filename] = '\0';
 
@@ -562,7 +569,7 @@ log_io_open(struct log_dir *dir, enum log_mode mode,
 {
 	struct log_io *l = NULL;
 	int save_errno;
-	const char *errmsg;
+	const char *errmsg = NULL;
 	/*
 	 * Check fopen() result the caller first thing, to
 	 * preserve the errno.
@@ -571,7 +578,7 @@ log_io_open(struct log_dir *dir, enum log_mode mode,
 		errmsg = strerror(errno);
 		goto error;
 	}
-	l = calloc(1, sizeof(*l));
+	l = (struct log_io *) calloc(1, sizeof(*l));
 	if (l == NULL) {
 		errmsg = strerror(errno);
 		goto error;
@@ -619,7 +626,8 @@ struct log_io *
 log_io_open_for_write(struct log_dir *dir, i64 lsn, enum log_suffix suffix)
 {
 	char *filename;
-
+	FILE *f;
+	int fd;
 	assert(lsn != 0);
 
 	if (suffix == INPROGRESS) {
@@ -638,12 +646,13 @@ log_io_open_for_write(struct log_dir *dir, i64 lsn, enum log_suffix suffix)
 	 * Open the <lsn>.<suffix>.inprogress file. If it exists,
 	 * open will fail.
 	 */
-	int fd = open(filename,
+
+	fd = open(filename,
 		      O_WRONLY | O_CREAT | O_EXCL | dir->open_wflags, 0664);
 	if (fd < 0)
 		goto error;
 	say_info("creating `%s'", filename);
-	FILE *f = fdopen(fd, "w");
+	f = fdopen(fd, "w");
 	return log_io_open(dir, LOG_WRITE, filename, suffix, f);
 error:
 	say_syserror("%s: failed to open `%s'", __func__, filename);
diff --git a/src/lua/cjson.m b/src/lua/cjson.cc
similarity index 99%
rename from src/lua/cjson.m
rename to src/lua/cjson.cc
index 112768bc97b309d54f217e95d077a2057882028e..45dd508511995d96790365d75fe555049653697d 100644
--- a/src/lua/cjson.m
+++ b/src/lua/cjson.cc
@@ -28,9 +28,11 @@
  */
 #include "lua/cjson.h"
 
+extern "C" {
 #include "lua.h"
 #include "lauxlib.h"
 #include "lualib.h"
+}
 
 int luaopen_cjson(lua_State *l);
 
diff --git a/src/lua/info.m b/src/lua/info.cc
similarity index 98%
rename from src/lua/info.m
rename to src/lua/info.cc
index 03bab51ec09f31a2b54f34d947d37ca7eb943d57..a62c3be3a2240a2c605276fcb4785d18ab866927 100644
--- a/src/lua/info.m
+++ b/src/lua/info.cc
@@ -30,9 +30,11 @@
 #include "lua/info.h"
 #include "lua/init.h"
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
 
 #include <say.h>
 #include <string.h>
diff --git a/src/lua/init.m b/src/lua/init.cc
similarity index 96%
rename from src/lua/init.m
rename to src/lua/init.cc
index 48e03146a32501711e4a89a01e769c4c26ac5302..b2b3a72a50dbe586c84fbc4b689b9ab3ce8931c4 100644
--- a/src/lua/init.m
+++ b/src/lua/init.cc
@@ -31,16 +31,16 @@
 #include "box/box.h"
 #include "tbuf.h"
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-
-#include "lj_obj.h"
-#include "lj_ctype.h"
-#include "lj_cdata.h"
-#include "lj_cconv.h"
-#include "lj_state.h"
-#include <ctype.h>
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include <lj_obj.h>
+#include <lj_ctype.h>
+#include <lj_cdata.h>
+#include <lj_cconv.h>
+#include <lj_state.h>
+} /* extern "C" */
 
 #include "fiber.h"
 #include "lua_ipc.h"
@@ -52,10 +52,13 @@
 #include "lua/session.h"
 #include "lua/cjson.h"
 
+#include <ctype.h>
 #include <sys/time.h>
 #include <sys/types.h>
 
-#include TARANTOOL_CONFIG
+extern "C" {
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 
 /**
  * tarantool start-up file
@@ -151,7 +154,7 @@ luaL_pushcdata(struct lua_State *L, CTypeID id, int bits)
 	GCcdata *cd = lj_cdata_new(cts, id, bits);
 	TValue *o = L->top;
 	setcdataV(L, o, cd);
-	lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), o, 0);
+	lj_cconv_ct_init(cts, ct, sz, (uint8_t *) cdataptr(cd), o, 0);
 	incr_top(L);
 	return cd;
 }
@@ -300,7 +303,7 @@ lbox_pushfiber(struct lua_State *L, struct fiber *f)
 		/* push the key back */
 		lua_pushlightuserdata(L, f);
 		/* create a new userdata */
-		void **ptr = lua_newuserdata(L, sizeof(void *));
+		void **ptr = (void **) lua_newuserdata(L, sizeof(void *));
 		*ptr = f;
 		luaL_getmetatable(L, fiberlib_name);
 		lua_setmetatable(L, -2);
@@ -324,7 +327,7 @@ lbox_pushfiber(struct lua_State *L, struct fiber *f)
 static struct fiber *
 lbox_checkfiber(struct lua_State *L, int index)
 {
-	return *(void **) luaL_checkudata(L, index, fiberlib_name);
+	return *(struct fiber **) luaL_checkudata(L, index, fiberlib_name);
 }
 
 static struct fiber *
@@ -335,7 +338,7 @@ lua_isfiber(struct lua_State *L, int narg)
 	luaL_getmetatable(L, fiberlib_name);
 	struct fiber *f = NULL;
 	if (lua_equal(L, -1, -2))
-		f = * (void **) lua_touserdata(L, narg);
+		f = * (struct fiber **) lua_touserdata(L, narg);
 	lua_pop(L, 2);
 	return f;
 }
@@ -401,7 +404,7 @@ box_lua_fiber_get_caller(struct lua_State *L)
 	lua_getfield(L, -1, "callers");
 	lua_pushthread(L);
 	lua_gettable(L, -2);
-	struct fiber *caller = lua_touserdata(L, -1);
+	struct fiber *caller = (struct fiber *) lua_touserdata(L, -1);
 	/* Pop the caller, the callers table, the fiberlib metatable. */
 	lua_pop(L, 3);
 	return caller;
@@ -484,13 +487,23 @@ box_lua_fiber_run(va_list ap __attribute__((unused)))
 	 * completion status plus whatever the coroutine main
 	 * function returns. Follow this style here.
 	 */
-	@try {
+	auto cleanup = [=] {
+		/*
+		 * If the coroutine has detached itself, collect
+		 * its resources here.
+		 */
+		luaL_unref(L, LUA_REGISTRYINDEX, coro_ref);
+	};
+
+	try {
 		lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
 		/* push completion status */
 		lua_pushboolean(L, true);
 		/* move 'true' to stack start */
 		lua_insert(L, 1);
-	} @catch (FiberCancelException *e) {
+
+		cleanup();
+	} catch (const FiberCancelException& e) {
 		box_lua_fiber_clear_coro(tarantool_L, fiber);
 		/*
 		 * Note: FiberCancelException leaves garbage on
@@ -498,20 +511,24 @@ box_lua_fiber_run(va_list ap __attribute__((unused)))
 		 * possible to cancel a fiber which is not
 		 * scheduled, and cancel() is synchronous.
 		 */
-		@throw;
-	} @catch (tnt_Exception *e) {
+
+		cleanup();
+		throw;
+	} catch (const Exception& e) {
 		/* pop any possible garbage */
 		lua_settop(L, 0);
 		/* completion status */
 		lua_pushboolean(L, false);
 		/* error message */
-		lua_pushstring(L, [e errmsg]);
+		lua_pushstring(L, e.errmsg());
 
 		if (box_lua_fiber_get_coro(tarantool_L, fiber) == NULL) {
 			/* The fiber is detached, log the error. */
-			[e log];
+			e.log();
 		}
-	} @catch (id allOthers) {
+
+		cleanup();
+	} catch (...) {
 		lua_settop(L, 1);
 		/*
 		 * The error message is already there.
@@ -525,12 +542,8 @@ box_lua_fiber_run(va_list ap __attribute__((unused)))
 			/* The fiber is detached, log the error. */
 			say_error("%s", lua_tostring(L, -1));
 		}
-	} @finally {
-		/*
-		 * If the coroutine has detached itself, collect
-		 * its resources here.
-		 */
-		luaL_unref(L, LUA_REGISTRYINDEX, coro_ref);
+
+		cleanup();
 	}
 	/*
 	 * L stack contains nothing but call results.
@@ -622,7 +635,7 @@ lbox_fiber_resume(struct lua_State *L)
 	assert(f->fid == fid);
 	tarantool_lua_set_out(child_L, NULL);
 	/* Find out the state of the child fiber. */
-	enum fiber_state child_state = lua_tointeger(child_L, -1);
+	enum fiber_state child_state = (enum fiber_state) lua_tointeger(child_L, -1);
 	lua_pop(child_L, 1);
 	/* Get the results */
 	nargs = lua_gettop(child_L);
@@ -1001,13 +1014,13 @@ lbox_pcall(struct lua_State *L)
 	 * Lua pcall() returns true/false for completion status
 	 * plus whatever the called function returns.
 	 */
-	@try {
+	try {
 		lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
 		/* push completion status */
 		lua_pushboolean(L, true);
 		/* move 'true' to stack start */
 		lua_insert(L, 1);
-	} @catch (ClientError *e) {
+	} catch (const ClientError& e) {
 		/*
 		 * Note: FiberCancelException passes through this
 		 * catch and thus leaves garbage on coroutine
@@ -1018,10 +1031,10 @@ lbox_pcall(struct lua_State *L)
 		/* completion status */
 		lua_pushboolean(L, false);
 		/* error message */
-		lua_pushstring(L, e->errmsg);
-	} @catch (tnt_Exception *e) {
-		@throw;
-	} @catch (id allOthers) {
+		lua_pushstring(L, e.errmsg());
+	} catch (const Exception& e) {
+		throw;
+	} catch (...) {
 		lua_settop(L, 1);
 		/* completion status */
 		lua_pushboolean(L, false);
@@ -1204,14 +1217,14 @@ tarantool_lua_dostring(struct lua_State *L, const char *str)
 		if (r)
 			return r;
 	}
-	@try {
+	try {
 		lua_call(L, 0, LUA_MULTRET);
-	} @catch (FiberCancelException *e) {
-		@throw;
-	} @catch (tnt_Exception *e) {
-		lua_pushstring(L, [e errmsg]);
+	} catch (const FiberCancelException& e) {
+		throw;
+	} catch (const Exception& e) {
+		lua_pushstring(L, e.errmsg());
 		return 1;
-	} @catch (id allOthers) {
+	} catch (...) {
 		return 1;
 	}
 	return 0;
@@ -1290,7 +1303,7 @@ tarantool_lua_load_cfg(struct lua_State *L, struct tarantool_cfg *cfg)
 	while ((key = tarantool_cfg_iterator_next(i, cfg, &value)) != NULL) {
 		if (value == NULL)
 			continue;
-		char *quote = is_string(value) ? "'" : "";
+		const char *quote = is_string(value) ? "'" : "";
 		if (strchr(key, '.') == NULL) {
 			lua_pushfstring(L, "box.cfg.%s = %s%s%s\n",
 					key, quote, value, quote);
diff --git a/src/lua/lua_ipc.m b/src/lua/lua_ipc.cc
similarity index 96%
rename from src/lua/lua_ipc.m
rename to src/lua/lua_ipc.cc
index 8b10960a5871c418b357d984774405eb00b0fe35..da40956ca606c96eb317436ed6e6d3dad5c8de34 100644
--- a/src/lua/lua_ipc.m
+++ b/src/lua/lua_ipc.cc
@@ -30,9 +30,11 @@
 
 #include <stdlib.h>
 
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
 
 #include "ipc.h"
 #include "lua/init.h"
@@ -58,7 +60,7 @@ lbox_ipc_channel(struct lua_State *L)
 	if (!ch)
 		luaL_error(L, "box.channel: Not enough memory");
 
-	void **ptr = lua_newuserdata(L, sizeof(void *));
+	void **ptr = (void **) lua_newuserdata(L, sizeof(void *));
 	luaL_getmetatable(L, channel_lib);
 
 	lua_pushstring(L, "rid");	/* first object id */
@@ -73,7 +75,7 @@ lbox_ipc_channel(struct lua_State *L)
 static inline struct ipc_channel *
 lbox_check_channel(struct lua_State *L, int narg)
 {
-	return * (void **) luaL_checkudata(L, narg, channel_lib);
+	return *(struct ipc_channel **) luaL_checkudata(L, narg, channel_lib);
 }
 
 static int
diff --git a/src/lua/lua_socket.m b/src/lua/lua_socket.cc
similarity index 93%
rename from src/lua/lua_socket.m
rename to src/lua/lua_socket.cc
index c341be5ed9095839e73e89e0ee806e6e2de53854..c855eda4c72c5d0b3f21475e5d1f93c0a438c649 100644
--- a/src/lua/lua_socket.m
+++ b/src/lua/lua_socket.cc
@@ -27,9 +27,12 @@
  * SUCH DAMAGE.
  */
 #include "lua_socket.h"
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
 
 #include "sio.h"
 #include "evio.h"
@@ -80,7 +83,8 @@ struct bio_socket {
 static int
 bio_pushsocket(struct lua_State *L, int socktype)
 {
-	struct bio_socket *s = lua_newuserdata(L, sizeof(struct bio_socket));
+	struct bio_socket *s = (struct bio_socket *)
+			lua_newuserdata(L, sizeof(struct bio_socket));
 	luaL_getmetatable(L, socketlib_name);
 	lua_setmetatable(L, -2);
 	coio_init(&s->io_r);
@@ -104,7 +108,7 @@ bio_checksocket(struct lua_State *L, int narg)
 	/* avoiding unnecessary luajit assert */
 	if (lua_gettop(L) < narg)
 		luaL_error(L, "box.socket: incorrect method call");
-	return luaL_checkudata(L, narg, socketlib_name);
+	return (struct bio_socket *) luaL_checkudata(L, narg, socketlib_name);
 }
 
 static inline struct bio_socket *
@@ -142,7 +146,7 @@ bio_initbuf(struct bio_socket *s)
 static inline int
 bio_pushstatus(struct lua_State *L, enum bio_status s)
 {
-	static char *status_strs[] = {"error", "timeout", "eof", "limit"};
+	static const char *status_strs[] = {"error", "timeout", "eof", "limit"};
 	lua_pushstring(L, status_strs[s]);
 	return 1;
 }
@@ -319,17 +323,22 @@ lbox_socket_connect(struct lua_State *L)
 		return bio_pushsockerror(L, s, errno);
 
 	evio_timeout_update(start, &delay);
-	@try {
+	try {
 		/* connect to a first available host */
-		if (coio_connect_addrinfo(&s->io_w, ai, delay))
+		int r = coio_connect_addrinfo(&s->io_w, ai, delay);
+		freeaddrinfo(ai);
+		if (r)
 			return bio_pushsockerror(L, s, ETIMEDOUT);
+
 		/* set coio reader socket */
 		s->io_r.fd = s->io_w.fd;
-	} @catch (SocketError *e) {
-		return bio_pushsockerror(L, s, errno);
-	} @finally {
+	} catch (const SocketError& e) {
+		say_error("catch(SocketError&)");
 		freeaddrinfo(ai);
+
+		return bio_pushsockerror(L, s, errno);
 	}
+
 	bio_initbuf(s);
 	/* Success */
 	lua_settop(L, 1);
@@ -372,19 +381,26 @@ lbox_socket_send(struct lua_State *L)
 	evio_timeout_update(start, &delay);
 
 	int rc;
-	@try {
+	try {
 		ssize_t nwr = coio_write_timeout(&s->io_w, buf, buf_size,
 						 delay);
 		if (nwr < buf_size) {
 			rc = bio_pushsenderror(L, s, nwr, ETIMEDOUT);
+			mutex_unlock(&s->io_w_mutex);
 			return rc;
 		}
-	} @catch (SocketError *e) {
+
+		mutex_unlock(&s->io_w_mutex);
+	} catch (const SocketError& e) {
+		mutex_unlock(&s->io_w_mutex);
+
 		rc = bio_pushsenderror(L, s, 0, errno);
 		return rc;
-	} @finally {
+	} catch (const Exception& e) {
 		mutex_unlock(&s->io_w_mutex);
+		throw;
 	}
+
 	/* case #1: Success */
 	lua_pushinteger(L, buf_size);
 	return 1;
@@ -439,15 +455,20 @@ lbox_socket_recv(struct lua_State *L)
 		to_read = sz - ibuf_size(in);
 
 		ssize_t nrd;
-		@try {
+		try {
 			nrd = coio_bread_timeout(&s->io_r, in, to_read,
 						 delay);
-		} @catch (SocketError *e) {
+			mutex_unlock(&s->io_r_mutex);
+		} catch (const SocketError& e) {
+			mutex_unlock(&s->io_r_mutex);
+
 			rc = bio_pushrecverror(L, s, errno);
 			return rc;
-		} @finally {
+		} catch (const Exception& e) {
 			mutex_unlock(&s->io_r_mutex);
+			throw;
 		}
+
 		if (nrd < to_read) {
 			/*  timeout or EOF. */
 			if (errno == ETIMEDOUT)
@@ -633,11 +654,11 @@ lbox_socket_readline(struct lua_State *L)
 	struct ibuf *in = &s->iob->in;
 	int rc;
 
-	@try {
+	try {
 		/* readline implementation uses a simple state machine
 		 * to determine current position of a possible
 		 * separator. */
-		struct readline_state *rs =
+		struct readline_state *rs = (struct readline_state *)
 			palloc(in->pool, sizeof(struct readline_state) * rs_size);
 		readline_state_init(L, rs, seplist);
 
@@ -647,6 +668,7 @@ lbox_socket_readline(struct lua_State *L)
 				lua_pushlstring(L, in->pos, bottom);
 				s->iob->in.pos += bottom;
 				bio_pushstatus(L, BIO_LIMIT);
+				mutex_unlock(&s->io_r_mutex);
 				return 2;
 			}
 
@@ -662,6 +684,7 @@ lbox_socket_readline(struct lua_State *L)
 						rc = bio_pushrecverror(L, s, ETIMEDOUT);
 					else
 						rc = bio_pusheof(L, s);
+					mutex_unlock(&s->io_r_mutex);
 					return rc;
 				}
 			}
@@ -673,11 +696,15 @@ lbox_socket_readline(struct lua_State *L)
 
 			evio_timeout_update(start, &delay);
 		}
-	} @catch (SocketError *e) {
+
+		mutex_unlock(&s->io_r_mutex);
+	} catch (const SocketError& e) {
+		mutex_unlock(&s->io_r_mutex);
 		rc = bio_pushrecverror(L, s, errno);
 		return rc;
-	} @finally {
+	} catch (const Exception& e) {
 		mutex_unlock(&s->io_r_mutex);
+		throw;
 	}
 
 	/* case #1: success, separator matched */
@@ -713,14 +740,16 @@ lbox_socket_bind(struct lua_State *L)
 	struct addrinfo *ai = coeio_resolve(s->socktype, host, port, timeout);
 	if (ai == NULL)
 		return bio_pusherror(L, s, errno);
-	@try {
+	try {
 		evio_bind_addrinfo(&s->io_w, ai);
-	} @catch (SocketError *e) {
+		freeaddrinfo(ai);
+	} catch (const SocketError& e) {
 		/* case #2: error */
-		return bio_pusherror(L, s, errno);
-	} @finally {
 		freeaddrinfo(ai);
+		say_error("socket SocketError&");
+		return bio_pusherror(L, s, errno);
 	}
+
 	/* case #1: Success */
 	lua_settop(L, 1);
 	return 1;
@@ -768,12 +797,12 @@ lbox_socket_accept(struct lua_State *L)
 	struct sockaddr_storage addr;
 	/* push client socket */
 	bio_pushsocket(L, SOCK_STREAM);
-	struct bio_socket *client = lua_touserdata(L, -1);
-	@try {
+	struct bio_socket *client = (struct bio_socket *) lua_touserdata(L, -1);
+	try {
 		client->io_w.fd = coio_accept(&s->io_w, (struct sockaddr_in*)&addr,
-		                             sizeof(addr), timeout);
+					     sizeof(addr), timeout);
 		client->io_r.fd = client->io_w.fd;
-	} @catch (SocketError *e) {
+	} catch (const SocketError& e) {
 		return bio_pusherror(L, s, errno);
 	}
 	/* get user host and port */
@@ -837,20 +866,24 @@ lbox_socket_sendto(struct lua_State *L)
 	}
 
 	size_t nwr;
-	@try {
+	try {
 		/* maybe init the socket */
 		if (! evio_is_active(&s->io_w))
 			evio_socket(&s->io_w, addr->sa_family, s->socktype, 0);
 		nwr = coio_sendto_timeout(&s->io_w, buf, buf_size, 0,
 					  (struct sockaddr_in*)addr, addrlen, delay);
-	} @catch (SocketError *e) {
+		if (a) {
+			freeaddrinfo(a);
+		}
+	} catch (const SocketError& e) {
 		/* case #2-3: error or timeout */
-		return bio_pushsenderror(L, s, 0, errno);
-	} @finally {
 		if (a) {
 			freeaddrinfo(a);
 		}
+		say_error("catch(SocketError&)");
+		return bio_pushsenderror(L, s, 0, errno);
 	}
+
 	if (nwr == 0) {
 		assert(errno == ETIMEDOUT);
 		return bio_pushsenderror(L, s, 0, ETIMEDOUT);
@@ -886,12 +919,12 @@ lbox_socket_recvfrom(struct lua_State *L)
 	struct sockaddr_storage addr;
 	struct ibuf *in = &s->iob->in;
 	size_t nrd;
-	@try {
+	try {
 		ibuf_reserve(in, buf_size);
 		nrd = coio_recvfrom_timeout(&s->io_w, in->pos, buf_size, 0,
-				            (struct sockaddr_in*)&addr,
-				            sizeof(addr), timeout);
-	} @catch (SocketError *e) {
+					    (struct sockaddr_in*)&addr,
+					    sizeof(addr), timeout);
+	} catch (const SocketError& e) {
 		return bio_pushrecverror(L, s, errno);
 	}
 	if (nrd == 0) {
diff --git a/src/lua/session.m b/src/lua/session.cc
similarity index 93%
rename from src/lua/session.m
rename to src/lua/session.cc
index 3f007b13d7e93a80c2a9b140b45d359df8a111ab..508c34247cbd689a78bc0d9fd9113d94090e57fe 100644
--- a/src/lua/session.m
+++ b/src/lua/session.cc
@@ -29,9 +29,11 @@
 #include "lua/session.h"
 #include "lua/init.h"
 
+extern "C" {
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
+}
 
 #include "fiber.h"
 #include "session.h"
@@ -102,7 +104,8 @@ static struct lbox_session_trigger on_disconnect =
 static void
 lbox_session_run_trigger(void *param)
 {
-	struct lbox_session_trigger *trigger = param;
+	struct lbox_session_trigger *trigger =
+			(struct lbox_session_trigger *) param;
 	/* Copy the referenced callable object object stack. */
 	lua_State *L = lua_newthread(tarantool_L);
 	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
@@ -110,15 +113,15 @@ lbox_session_run_trigger(void *param)
 	/** Move the function to be called to the new coro. */
 	lua_xmove(tarantool_L, L, 1);
 
-	@try {
+	try {
 		lua_call(L, 0, 0);
-	} @catch (tnt_Exception *e) {
-		@throw;
-	} @catch ( id allOthers ) {
-		tnt_raise(ClientError, :ER_PROC_LUA,
-			  lua_tostring(L, -1));
-	} @finally {
 		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
+	} catch (const Exception& e) {
+		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
+		throw;
+	} catch (...) {
+		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
+		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
 	}
 }
 
diff --git a/src/lua/slab.m b/src/lua/slab.cc
similarity index 96%
rename from src/lua/slab.m
rename to src/lua/slab.cc
index 538e747c30794d9b2fcf9a6bd78711666237af2a..ccffceeb0daceefbb792076a944c01bfb7f553a3 100644
--- a/src/lua/slab.m
+++ b/src/lua/slab.cc
@@ -27,17 +27,21 @@
  * SUCH DAMAGE.
  */
 #include "lua/slab.h"
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
+
 #include "lua/init.h"
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
 #include <salloc.h>
 
 /** A callback passed into salloc_stat() and invoked for every slab class. */
 static int
 salloc_stat_lua_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
 {
-	struct lua_State *L = cb_ctx;
+	struct lua_State *L = (struct lua_State *) cb_ctx;
 
 	/*
 	 * Create a Lua table for every slab class. A class is
diff --git a/src/lua/stat.m b/src/lua/stat.cc
similarity index 93%
rename from src/lua/stat.m
rename to src/lua/stat.cc
index f0652327905d1221bf1479da51d22e1c55f712e0..5fdfe919d1e0ee0e7b7aa0de02576734340f1397 100644
--- a/src/lua/stat.m
+++ b/src/lua/stat.cc
@@ -1,4 +1,5 @@
 /*
+ *
  * Redistribution and use in source and binary forms, with or
  * without modification, are permitted provided that the following
  * conditions are met:
@@ -27,12 +28,15 @@
  * SUCH DAMAGE.
  */
 #include "lua/stat.h"
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+
 #include <string.h>
 #include <stat.h>
 
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
 
 static void
 fill_stat_item(struct lua_State *L, int rps, i64 total)
@@ -49,7 +53,7 @@ fill_stat_item(struct lua_State *L, int rps, i64 total)
 static int
 set_stat_item(const char *name, int rps, i64 total, void *cb_ctx)
 {
-	struct lua_State *L = cb_ctx;
+	struct lua_State *L = (struct lua_State *) cb_ctx;
 
 	lua_pushstring(L, name);
 	lua_newtable(L);
@@ -68,7 +72,7 @@ set_stat_item(const char *name, int rps, i64 total, void *cb_ctx)
 static int
 seek_stat_item(const char *name, int rps, i64 total, void *cb_ctx)
 {
-	struct lua_State *L = cb_ctx;
+	struct lua_State *L = (struct lua_State *) cb_ctx;
 	if (strcmp(name, lua_tostring(L, -1)) != 0)
 		return 0;
 
diff --git a/src/lua/uuid.m b/src/lua/uuid.cc
similarity index 95%
rename from src/lua/uuid.m
rename to src/lua/uuid.cc
index 3b495e8c2e7720cd1e9d79cc2f47a0c1f305eaf7..9c2e3d4eacfb883583aafde91bd982f993bbb923 100644
--- a/src/lua/uuid.m
+++ b/src/lua/uuid.cc
@@ -31,9 +31,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <dlfcn.h>
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
+
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} /* extern "C" */
 
 /** libuuid API */
 typedef unsigned char uuid_t[16];
@@ -70,7 +73,7 @@ loaddl_and_call(struct lua_State *L, box_function f)
 	if (!libuuid)
 		return luaL_error(L, "box.uuid(): %s", dlerror());
 
-	uuid_generate = dlsym(libuuid, "uuid_generate");
+	uuid_generate = (decltype(uuid_generate)) dlsym(libuuid, "uuid_generate");
 	if (!uuid_generate) {
 		lua_pushfstring(L, "box.uuid(): %s", dlerror());
 		dlclose(libuuid);
diff --git a/src/memcached-grammar.m b/src/memcached-grammar.cc
similarity index 87%
rename from src/memcached-grammar.m
rename to src/memcached-grammar.cc
index e79e7e187367096acf651ea42c56adedf79ba7a1..7b177d3c14b5a3a5e3ceb7c872416ea7281db76a 100644
--- a/src/memcached-grammar.m
+++ b/src/memcached-grammar.cc
@@ -30,7 +30,7 @@
  */
 
 
-#line 34 "src/memcached-grammar.m"
+#line 34 "src/memcached-grammar.cc"
 static const int memcached_start = 1;
 static const int memcached_first_final = 197;
 static const int memcached_error = 0;
@@ -69,12 +69,12 @@ memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
 	say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p);
 
 	
-#line 73 "src/memcached-grammar.m"
+#line 73 "src/memcached-grammar.cc"
 	{
 	cs = memcached_start;
 	}
 
-#line 78 "src/memcached-grammar.m"
+#line 78 "src/memcached-grammar.cc"
 	{
 	if ( p == pe )
 		goto _test_eof;
@@ -146,7 +146,7 @@ case 5:
 		goto st0;
 	goto tr15;
 tr15:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -162,7 +162,7 @@ case 5:
 	if ( ++p == pe )
 		goto _test_eof6;
 case 6:
-#line 166 "src/memcached-grammar.m"
+#line 166 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st7;
 	goto st0;
@@ -176,49 +176,49 @@ case 7:
 		goto tr17;
 	goto st0;
 tr17:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st8;
 st8:
 	if ( ++p == pe )
 		goto _test_eof8;
 case 8:
-#line 187 "src/memcached-grammar.m"
+#line 187 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr18;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st8;
 	goto st0;
 tr18:
-#line 245 "src/memcached-grammar.rl"
+#line 244 "src/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st9;
 st9:
 	if ( ++p == pe )
 		goto _test_eof9;
 case 9:
-#line 201 "src/memcached-grammar.m"
+#line 201 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st9;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr21;
 	goto st0;
 tr21:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st10;
 st10:
 	if ( ++p == pe )
 		goto _test_eof10;
 case 10:
-#line 215 "src/memcached-grammar.m"
+#line 215 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr22;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st10;
 	goto st0;
 tr22:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -229,21 +229,21 @@ case 10:
 	if ( ++p == pe )
 		goto _test_eof11;
 case 11:
-#line 233 "src/memcached-grammar.m"
+#line 233 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st11;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr25;
 	goto st0;
 tr25:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st12;
 st12:
 	if ( ++p == pe )
 		goto _test_eof12;
 case 12:
-#line 247 "src/memcached-grammar.m"
+#line 247 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr26;
 		case 13: goto tr27;
@@ -253,11 +253,11 @@ case 12:
 		goto st12;
 	goto st0;
 tr26:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -280,7 +280,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -297,9 +297,9 @@ case 12:
 		}
 	goto st197;
 tr30:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -322,7 +322,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -339,11 +339,11 @@ case 12:
 		}
 	goto st197;
 tr39:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -366,7 +366,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -383,11 +383,11 @@ case 12:
 		}
 	goto st197;
 tr58:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -410,7 +410,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -445,9 +445,9 @@ case 12:
 		}
 	goto st197;
 tr62:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -470,7 +470,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -505,11 +505,11 @@ case 12:
 		}
 	goto st197;
 tr71:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -532,7 +532,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -567,11 +567,11 @@ case 12:
 		}
 	goto st197;
 tr91:
-#line 247 "src/memcached-grammar.rl"
+#line 246 "src/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -594,7 +594,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -613,9 +613,9 @@ case 12:
 		}
 	goto st197;
 tr95:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -638,7 +638,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -657,11 +657,11 @@ case 12:
 		}
 	goto st197;
 tr105:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -684,7 +684,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -703,11 +703,11 @@ case 12:
 		}
 	goto st197;
 tr118:
-#line 248 "src/memcached-grammar.rl"
+#line 247 "src/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -731,7 +731,7 @@ case 12:
 				value_len = load_varint32(&field);
 
 				if (is_numeric(field, value_len)) {
-					value = natoq(field, field + value_len);
+					value = natoq((char *) field, (char *) field + value_len);
 
 					if (incr_sign > 0) {
 						value += incr;
@@ -746,20 +746,19 @@ case 12:
 					flags = m->flags;
 
 					b = tbuf_new(fiber->gc_pool);
-					tbuf_printf(b, "%"PRIu64, value);
+					tbuf_printf(b, "%" PRIu64, value);
 					data = b->data;
 					bytes = b->size;
 
 					stats.cmd_set++;
-					@try {
+					try {
 						store(key, exptime, flags, bytes, data);
 						stats.total_items++;
 						obuf_dup(out, b->data, b->size);
 						obuf_dup(out, "\r\n", 2);
-					}
-					@catch (ClientError *e) {
+					} catch (const ClientError& e) {
 						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e->errmsg, strlen(e->errmsg));
+						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 						obuf_dup(out, "\r\n", 2);
 					}
 				} else {
@@ -770,9 +769,9 @@ case 12:
 		}
 	goto st197;
 tr122:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -796,7 +795,7 @@ case 12:
 				value_len = load_varint32(&field);
 
 				if (is_numeric(field, value_len)) {
-					value = natoq(field, field + value_len);
+					value = natoq((char *) field, (char *) field + value_len);
 
 					if (incr_sign > 0) {
 						value += incr;
@@ -811,20 +810,19 @@ case 12:
 					flags = m->flags;
 
 					b = tbuf_new(fiber->gc_pool);
-					tbuf_printf(b, "%"PRIu64, value);
+					tbuf_printf(b, "%" PRIu64, value);
 					data = b->data;
 					bytes = b->size;
 
 					stats.cmd_set++;
-					@try {
+					try {
 						store(key, exptime, flags, bytes, data);
 						stats.total_items++;
 						obuf_dup(out, b->data, b->size);
 						obuf_dup(out, "\r\n", 2);
-					}
-					@catch (ClientError *e) {
+					} catch (const ClientError& e) {
 						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e->errmsg, strlen(e->errmsg));
+						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 						obuf_dup(out, "\r\n", 2);
 					}
 				} else {
@@ -835,11 +833,11 @@ case 12:
 		}
 	goto st197;
 tr132:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -863,7 +861,7 @@ case 12:
 				value_len = load_varint32(&field);
 
 				if (is_numeric(field, value_len)) {
-					value = natoq(field, field + value_len);
+					value = natoq((char *) field, (char *) field + value_len);
 
 					if (incr_sign > 0) {
 						value += incr;
@@ -878,20 +876,19 @@ case 12:
 					flags = m->flags;
 
 					b = tbuf_new(fiber->gc_pool);
-					tbuf_printf(b, "%"PRIu64, value);
+					tbuf_printf(b, "%" PRIu64, value);
 					data = b->data;
 					bytes = b->size;
 
 					stats.cmd_set++;
-					@try {
+					try {
 						store(key, exptime, flags, bytes, data);
 						stats.total_items++;
 						obuf_dup(out, b->data, b->size);
 						obuf_dup(out, "\r\n", 2);
-					}
-					@catch (ClientError *e) {
+					} catch (const ClientError& e) {
 						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e->errmsg, strlen(e->errmsg));
+						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 						obuf_dup(out, "\r\n", 2);
 					}
 				} else {
@@ -902,107 +899,107 @@ case 12:
 		}
 	goto st197;
 tr141:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 179 "src/memcached-grammar.rl"
+#line 178 "src/memcached-grammar.rl"
 	{
 			key = tbuf_read_field(keys);
 			struct tuple *tuple = find(key);
 			if (tuple == NULL || expired(tuple)) {
 				obuf_dup(out, "NOT_FOUND\r\n", 11);
 			} else {
-				@try {
-					delete(key);
+				try {
+					remove(key);
 					obuf_dup(out, "DELETED\r\n", 9);
 				}
-				@catch (ClientError *e) {
+				catch (const ClientError& e) {
 					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e->errmsg, strlen(e->errmsg));
+					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 					obuf_dup(out, "\r\n", 2);
 				}
 			}
 		}
 	goto st197;
 tr146:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
 				exptime = exptime + ev_now();
 		}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 179 "src/memcached-grammar.rl"
+#line 178 "src/memcached-grammar.rl"
 	{
 			key = tbuf_read_field(keys);
 			struct tuple *tuple = find(key);
 			if (tuple == NULL || expired(tuple)) {
 				obuf_dup(out, "NOT_FOUND\r\n", 11);
 			} else {
-				@try {
-					delete(key);
+				try {
+					remove(key);
 					obuf_dup(out, "DELETED\r\n", 9);
 				}
-				@catch (ClientError *e) {
+				catch (const ClientError& e) {
 					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e->errmsg, strlen(e->errmsg));
+					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 					obuf_dup(out, "\r\n", 2);
 				}
 			}
 		}
 	goto st197;
 tr157:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 179 "src/memcached-grammar.rl"
+#line 178 "src/memcached-grammar.rl"
 	{
 			key = tbuf_read_field(keys);
 			struct tuple *tuple = find(key);
 			if (tuple == NULL || expired(tuple)) {
 				obuf_dup(out, "NOT_FOUND\r\n", 11);
 			} else {
-				@try {
-					delete(key);
+				try {
+					remove(key);
 					obuf_dup(out, "DELETED\r\n", 9);
 				}
-				@catch (ClientError *e) {
+				catch (const ClientError& e) {
 					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e->errmsg, strlen(e->errmsg));
+					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 					obuf_dup(out, "\r\n", 2);
 				}
 			}
 		}
 	goto st197;
 tr169:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 208 "src/memcached-grammar.rl"
+#line 207 "src/memcached-grammar.rl"
 	{
 			struct fiber *f = fiber_new("flush_all", flush_all);
 			fiber_call(f, flush_delay);
@@ -1010,17 +1007,17 @@ case 12:
 		}
 	goto st197;
 tr174:
-#line 249 "src/memcached-grammar.rl"
+#line 248 "src/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 208 "src/memcached-grammar.rl"
+#line 207 "src/memcached-grammar.rl"
 	{
 			struct fiber *f = fiber_new("flush_all", flush_all);
 			fiber_call(f, flush_delay);
@@ -1028,17 +1025,17 @@ case 12:
 		}
 	goto st197;
 tr185:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 208 "src/memcached-grammar.rl"
+#line 207 "src/memcached-grammar.rl"
 	{
 			struct fiber *f = fiber_new("flush_all", flush_all);
 			fiber_call(f, flush_delay);
@@ -1046,46 +1043,46 @@ case 12:
 		}
 	goto st197;
 tr195:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 197 "src/memcached-grammar.rl"
+#line 196 "src/memcached-grammar.rl"
 	{
-			@try {
+			try {
 				memcached_get(out, keys_count, keys, show_cas);
-			} @catch (ClientError *e) {
+			} catch (const ClientError& e) {
 				obuf_rollback_to_svp(out, &obuf_svp);
 				obuf_dup(out, "SERVER_ERROR ", 13);
-				obuf_dup(out, e->errmsg, strlen(e->errmsg));
+				obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 				obuf_dup(out, "\r\n", 2);
 			}
 		}
 	goto st197;
 tr213:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 218 "src/memcached-grammar.rl"
+#line 217 "src/memcached-grammar.rl"
 	{
 			return -1;
 		}
 	goto st197;
 tr233:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1108,7 +1105,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1125,9 +1122,9 @@ case 12:
 		}
 	goto st197;
 tr237:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1150,7 +1147,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1167,11 +1164,11 @@ case 12:
 		}
 	goto st197;
 tr246:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1194,7 +1191,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1211,11 +1208,11 @@ case 12:
 		}
 	goto st197;
 tr263:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1238,7 +1235,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1251,9 +1248,9 @@ case 12:
 		}
 	goto st197;
 tr267:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1276,7 +1273,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1289,11 +1286,11 @@ case 12:
 		}
 	goto st197;
 tr276:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 251 "src/memcached-grammar.rl"
+#line 250 "src/memcached-grammar.rl"
 	{
 			size_t parsed = p - in->pos;
 			while (ibuf_size(in) - parsed < bytes + 2) {
@@ -1316,7 +1313,7 @@ case 12:
 				goto exit;
 			}
 		}
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
@@ -1329,15 +1326,15 @@ case 12:
 		}
 	goto st197;
 tr281:
-#line 280 "src/memcached-grammar.rl"
+#line 279 "src/memcached-grammar.rl"
 	{ p++; }
-#line 274 "src/memcached-grammar.rl"
+#line 273 "src/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - in->pos;
 			in->pos = p;
 		}
-#line 214 "src/memcached-grammar.rl"
+#line 213 "src/memcached-grammar.rl"
 	{
 			print_stats(out);
 		}
@@ -1346,33 +1343,33 @@ case 12:
 	if ( ++p == pe )
 		goto _test_eof197;
 case 197:
-#line 1350 "src/memcached-grammar.m"
+#line 1347 "src/memcached-grammar.cc"
 	goto st0;
 tr27:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st13;
 tr40:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st13;
 st13:
 	if ( ++p == pe )
 		goto _test_eof13;
 case 13:
-#line 1364 "src/memcached-grammar.m"
+#line 1361 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr30;
 	goto st0;
 tr28:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st14;
 st14:
 	if ( ++p == pe )
 		goto _test_eof14;
 case 14:
-#line 1376 "src/memcached-grammar.m"
+#line 1373 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 32: goto st14;
 		case 78: goto st15;
@@ -1486,18 +1483,18 @@ case 26:
 		goto tr45;
 	goto st0;
 tr45:
-#line 288 "src/memcached-grammar.rl"
+#line 287 "src/memcached-grammar.rl"
 	{append = true; }
 	goto st27;
 tr209:
-#line 289 "src/memcached-grammar.rl"
+#line 288 "src/memcached-grammar.rl"
 	{append = false;}
 	goto st27;
 st27:
 	if ( ++p == pe )
 		goto _test_eof27;
 case 27:
-#line 1501 "src/memcached-grammar.m"
+#line 1498 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st27;
@@ -1506,7 +1503,7 @@ case 27:
 		goto st0;
 	goto tr46;
 tr46:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1522,7 +1519,7 @@ case 27:
 	if ( ++p == pe )
 		goto _test_eof28;
 case 28:
-#line 1526 "src/memcached-grammar.m"
+#line 1523 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st29;
 	goto st0;
@@ -1536,49 +1533,49 @@ case 29:
 		goto tr49;
 	goto st0;
 tr49:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st30;
 st30:
 	if ( ++p == pe )
 		goto _test_eof30;
 case 30:
-#line 1547 "src/memcached-grammar.m"
+#line 1544 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr50;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st30;
 	goto st0;
 tr50:
-#line 245 "src/memcached-grammar.rl"
+#line 244 "src/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st31;
 st31:
 	if ( ++p == pe )
 		goto _test_eof31;
 case 31:
-#line 1561 "src/memcached-grammar.m"
+#line 1558 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st31;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr53;
 	goto st0;
 tr53:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st32;
 st32:
 	if ( ++p == pe )
 		goto _test_eof32;
 case 32:
-#line 1575 "src/memcached-grammar.m"
+#line 1572 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr54;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st32;
 	goto st0;
 tr54:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1589,21 +1586,21 @@ case 32:
 	if ( ++p == pe )
 		goto _test_eof33;
 case 33:
-#line 1593 "src/memcached-grammar.m"
+#line 1590 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st33;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr57;
 	goto st0;
 tr57:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st34;
 st34:
 	if ( ++p == pe )
 		goto _test_eof34;
 case 34:
-#line 1607 "src/memcached-grammar.m"
+#line 1604 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr58;
 		case 13: goto tr59;
@@ -1613,30 +1610,30 @@ case 34:
 		goto st34;
 	goto st0;
 tr59:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st35;
 tr72:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st35;
 st35:
 	if ( ++p == pe )
 		goto _test_eof35;
 case 35:
-#line 1628 "src/memcached-grammar.m"
+#line 1625 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr62;
 	goto st0;
 tr60:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st36;
 st36:
 	if ( ++p == pe )
 		goto _test_eof36;
 case 36:
-#line 1640 "src/memcached-grammar.m"
+#line 1637 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 32: goto st36;
 		case 78: goto st37;
@@ -1743,7 +1740,7 @@ case 47:
 		goto st0;
 	goto tr76;
 tr76:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1759,7 +1756,7 @@ case 47:
 	if ( ++p == pe )
 		goto _test_eof48;
 case 48:
-#line 1763 "src/memcached-grammar.m"
+#line 1760 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st49;
 	goto st0;
@@ -1773,49 +1770,49 @@ case 49:
 		goto tr78;
 	goto st0;
 tr78:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st50;
 st50:
 	if ( ++p == pe )
 		goto _test_eof50;
 case 50:
-#line 1784 "src/memcached-grammar.m"
+#line 1781 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr79;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st50;
 	goto st0;
 tr79:
-#line 245 "src/memcached-grammar.rl"
+#line 244 "src/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st51;
 st51:
 	if ( ++p == pe )
 		goto _test_eof51;
 case 51:
-#line 1798 "src/memcached-grammar.m"
+#line 1795 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st51;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr82;
 	goto st0;
 tr82:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st52;
 st52:
 	if ( ++p == pe )
 		goto _test_eof52;
 case 52:
-#line 1812 "src/memcached-grammar.m"
+#line 1809 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr83;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st52;
 	goto st0;
 tr83:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1826,49 +1823,49 @@ case 52:
 	if ( ++p == pe )
 		goto _test_eof53;
 case 53:
-#line 1830 "src/memcached-grammar.m"
+#line 1827 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st53;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr86;
 	goto st0;
 tr86:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st54;
 st54:
 	if ( ++p == pe )
 		goto _test_eof54;
 case 54:
-#line 1844 "src/memcached-grammar.m"
+#line 1841 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr87;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st54;
 	goto st0;
 tr87:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st55;
 st55:
 	if ( ++p == pe )
 		goto _test_eof55;
 case 55:
-#line 1858 "src/memcached-grammar.m"
+#line 1855 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st55;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr90;
 	goto st0;
 tr90:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st56;
 st56:
 	if ( ++p == pe )
 		goto _test_eof56;
 case 56:
-#line 1872 "src/memcached-grammar.m"
+#line 1869 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr91;
 		case 13: goto tr92;
@@ -1878,30 +1875,30 @@ case 56:
 		goto st56;
 	goto st0;
 tr106:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st57;
 tr92:
-#line 247 "src/memcached-grammar.rl"
+#line 246 "src/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
 	goto st57;
 st57:
 	if ( ++p == pe )
 		goto _test_eof57;
 case 57:
-#line 1893 "src/memcached-grammar.m"
+#line 1890 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr95;
 	goto st0;
 tr93:
-#line 247 "src/memcached-grammar.rl"
+#line 246 "src/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
 	goto st58;
 st58:
 	if ( ++p == pe )
 		goto _test_eof58;
 case 58:
-#line 1905 "src/memcached-grammar.m"
+#line 1902 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -1975,14 +1972,14 @@ case 65:
 	}
 	goto st0;
 tr107:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st66;
 st66:
 	if ( ++p == pe )
 		goto _test_eof66;
 case 66:
-#line 1986 "src/memcached-grammar.m"
+#line 1983 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -2026,18 +2023,18 @@ case 70:
 		goto tr113;
 	goto st0;
 tr113:
-#line 297 "src/memcached-grammar.rl"
+#line 296 "src/memcached-grammar.rl"
 	{incr_sign = -1;}
 	goto st71;
 tr202:
-#line 296 "src/memcached-grammar.rl"
+#line 295 "src/memcached-grammar.rl"
 	{incr_sign = 1; }
 	goto st71;
 st71:
 	if ( ++p == pe )
 		goto _test_eof71;
 case 71:
-#line 2041 "src/memcached-grammar.m"
+#line 2038 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st71;
@@ -2046,7 +2043,7 @@ case 71:
 		goto st0;
 	goto tr114;
 tr114:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2062,7 +2059,7 @@ case 71:
 	if ( ++p == pe )
 		goto _test_eof72;
 case 72:
-#line 2066 "src/memcached-grammar.m"
+#line 2063 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st73;
 	goto st0;
@@ -2076,14 +2073,14 @@ case 73:
 		goto tr117;
 	goto st0;
 tr117:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st74;
 st74:
 	if ( ++p == pe )
 		goto _test_eof74;
 case 74:
-#line 2087 "src/memcached-grammar.m"
+#line 2084 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr118;
 		case 13: goto tr119;
@@ -2093,30 +2090,30 @@ case 74:
 		goto st74;
 	goto st0;
 tr133:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st75;
 tr119:
-#line 248 "src/memcached-grammar.rl"
+#line 247 "src/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
 	goto st75;
 st75:
 	if ( ++p == pe )
 		goto _test_eof75;
 case 75:
-#line 2108 "src/memcached-grammar.m"
+#line 2105 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr122;
 	goto st0;
 tr120:
-#line 248 "src/memcached-grammar.rl"
+#line 247 "src/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
 	goto st76;
 st76:
 	if ( ++p == pe )
 		goto _test_eof76;
 case 76:
-#line 2120 "src/memcached-grammar.m"
+#line 2117 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2190,14 +2187,14 @@ case 83:
 	}
 	goto st0;
 tr134:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st84;
 st84:
 	if ( ++p == pe )
 		goto _test_eof84;
 case 84:
-#line 2201 "src/memcached-grammar.m"
+#line 2198 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2250,7 +2247,7 @@ case 89:
 		goto st0;
 	goto tr140;
 tr140:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2266,7 +2263,7 @@ case 89:
 	if ( ++p == pe )
 		goto _test_eof90;
 case 90:
-#line 2270 "src/memcached-grammar.m"
+#line 2267 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2274,7 +2271,7 @@ case 90:
 	}
 	goto st0;
 tr147:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2282,14 +2279,14 @@ case 90:
 		}
 	goto st91;
 tr158:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st91;
 st91:
 	if ( ++p == pe )
 		goto _test_eof91;
 case 91:
-#line 2293 "src/memcached-grammar.m"
+#line 2290 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr141;
 	goto st0;
@@ -2308,14 +2305,14 @@ case 92:
 		goto tr144;
 	goto st0;
 tr144:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st93;
 st93:
 	if ( ++p == pe )
 		goto _test_eof93;
 case 93:
-#line 2319 "src/memcached-grammar.m"
+#line 2316 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr146;
 		case 13: goto tr147;
@@ -2325,7 +2322,7 @@ case 93:
 		goto st93;
 	goto st0;
 tr148:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2336,7 +2333,7 @@ case 93:
 	if ( ++p == pe )
 		goto _test_eof94;
 case 94:
-#line 2340 "src/memcached-grammar.m"
+#line 2337 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2410,14 +2407,14 @@ case 101:
 	}
 	goto st0;
 tr159:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st102;
 st102:
 	if ( ++p == pe )
 		goto _test_eof102;
 case 102:
-#line 2421 "src/memcached-grammar.m"
+#line 2418 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2505,18 +2502,18 @@ case 111:
 	}
 	goto st0;
 tr186:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st112;
 tr175:
-#line 249 "src/memcached-grammar.rl"
+#line 248 "src/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st112;
 st112:
 	if ( ++p == pe )
 		goto _test_eof112;
 case 112:
-#line 2520 "src/memcached-grammar.m"
+#line 2517 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr169;
 	goto st0;
@@ -2535,14 +2532,14 @@ case 113:
 		goto tr172;
 	goto st0;
 tr172:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st114;
 st114:
 	if ( ++p == pe )
 		goto _test_eof114;
 case 114:
-#line 2546 "src/memcached-grammar.m"
+#line 2543 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr174;
 		case 13: goto tr175;
@@ -2552,14 +2549,14 @@ case 114:
 		goto st114;
 	goto st0;
 tr176:
-#line 249 "src/memcached-grammar.rl"
+#line 248 "src/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st115;
 st115:
 	if ( ++p == pe )
 		goto _test_eof115;
 case 115:
-#line 2563 "src/memcached-grammar.m"
+#line 2560 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2633,14 +2630,14 @@ case 122:
 	}
 	goto st0;
 tr187:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st123;
 st123:
 	if ( ++p == pe )
 		goto _test_eof123;
 case 123:
-#line 2644 "src/memcached-grammar.m"
+#line 2641 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2676,18 +2673,18 @@ case 126:
 	}
 	goto st0;
 tr191:
-#line 293 "src/memcached-grammar.rl"
+#line 292 "src/memcached-grammar.rl"
 	{show_cas = false;}
 	goto st127;
 tr198:
-#line 294 "src/memcached-grammar.rl"
+#line 293 "src/memcached-grammar.rl"
 	{show_cas = true;}
 	goto st127;
 st127:
 	if ( ++p == pe )
 		goto _test_eof127;
 case 127:
-#line 2691 "src/memcached-grammar.m"
+#line 2688 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st127;
@@ -2696,7 +2693,7 @@ case 127:
 		goto st0;
 	goto tr193;
 tr193:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2712,7 +2709,7 @@ case 127:
 	if ( ++p == pe )
 		goto _test_eof128;
 case 128:
-#line 2716 "src/memcached-grammar.m"
+#line 2713 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr195;
 		case 13: goto st129;
@@ -2955,7 +2952,7 @@ case 155:
 		goto st0;
 	goto tr222;
 tr222:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2971,7 +2968,7 @@ case 155:
 	if ( ++p == pe )
 		goto _test_eof156;
 case 156:
-#line 2975 "src/memcached-grammar.m"
+#line 2972 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st157;
 	goto st0;
@@ -2985,49 +2982,49 @@ case 157:
 		goto tr224;
 	goto st0;
 tr224:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st158;
 st158:
 	if ( ++p == pe )
 		goto _test_eof158;
 case 158:
-#line 2996 "src/memcached-grammar.m"
+#line 2993 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr225;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st158;
 	goto st0;
 tr225:
-#line 245 "src/memcached-grammar.rl"
+#line 244 "src/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st159;
 st159:
 	if ( ++p == pe )
 		goto _test_eof159;
 case 159:
-#line 3010 "src/memcached-grammar.m"
+#line 3007 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st159;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr228;
 	goto st0;
 tr228:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st160;
 st160:
 	if ( ++p == pe )
 		goto _test_eof160;
 case 160:
-#line 3024 "src/memcached-grammar.m"
+#line 3021 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr229;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st160;
 	goto st0;
 tr229:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -3038,21 +3035,21 @@ case 160:
 	if ( ++p == pe )
 		goto _test_eof161;
 case 161:
-#line 3042 "src/memcached-grammar.m"
+#line 3039 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st161;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr232;
 	goto st0;
 tr232:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st162;
 st162:
 	if ( ++p == pe )
 		goto _test_eof162;
 case 162:
-#line 3056 "src/memcached-grammar.m"
+#line 3053 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr233;
 		case 13: goto tr234;
@@ -3062,30 +3059,30 @@ case 162:
 		goto st162;
 	goto st0;
 tr234:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st163;
 tr247:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st163;
 st163:
 	if ( ++p == pe )
 		goto _test_eof163;
 case 163:
-#line 3077 "src/memcached-grammar.m"
+#line 3074 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr237;
 	goto st0;
 tr235:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st164;
 st164:
 	if ( ++p == pe )
 		goto _test_eof164;
 case 164:
-#line 3089 "src/memcached-grammar.m"
+#line 3086 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 32: goto st164;
 		case 78: goto st165;
@@ -3194,7 +3191,7 @@ case 175:
 		goto st0;
 	goto tr252;
 tr252:
-#line 223 "src/memcached-grammar.rl"
+#line 222 "src/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -3210,7 +3207,7 @@ case 175:
 	if ( ++p == pe )
 		goto _test_eof176;
 case 176:
-#line 3214 "src/memcached-grammar.m"
+#line 3211 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st177;
 	goto st0;
@@ -3224,49 +3221,49 @@ case 177:
 		goto tr254;
 	goto st0;
 tr254:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st178;
 st178:
 	if ( ++p == pe )
 		goto _test_eof178;
 case 178:
-#line 3235 "src/memcached-grammar.m"
+#line 3232 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr255;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st178;
 	goto st0;
 tr255:
-#line 245 "src/memcached-grammar.rl"
+#line 244 "src/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st179;
 st179:
 	if ( ++p == pe )
 		goto _test_eof179;
 case 179:
-#line 3249 "src/memcached-grammar.m"
+#line 3246 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st179;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr258;
 	goto st0;
 tr258:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st180;
 st180:
 	if ( ++p == pe )
 		goto _test_eof180;
 case 180:
-#line 3263 "src/memcached-grammar.m"
+#line 3260 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto tr259;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st180;
 	goto st0;
 tr259:
-#line 238 "src/memcached-grammar.rl"
+#line 237 "src/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -3277,21 +3274,21 @@ case 180:
 	if ( ++p == pe )
 		goto _test_eof181;
 case 181:
-#line 3281 "src/memcached-grammar.m"
+#line 3278 "src/memcached-grammar.cc"
 	if ( (*p) == 32 )
 		goto st181;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr262;
 	goto st0;
 tr262:
-#line 222 "src/memcached-grammar.rl"
+#line 221 "src/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st182;
 st182:
 	if ( ++p == pe )
 		goto _test_eof182;
 case 182:
-#line 3295 "src/memcached-grammar.m"
+#line 3292 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 10: goto tr263;
 		case 13: goto tr264;
@@ -3301,30 +3298,30 @@ case 182:
 		goto st182;
 	goto st0;
 tr264:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st183;
 tr277:
-#line 282 "src/memcached-grammar.rl"
+#line 281 "src/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st183;
 st183:
 	if ( ++p == pe )
 		goto _test_eof183;
 case 183:
-#line 3316 "src/memcached-grammar.m"
+#line 3313 "src/memcached-grammar.cc"
 	if ( (*p) == 10 )
 		goto tr267;
 	goto st0;
 tr265:
-#line 246 "src/memcached-grammar.rl"
+#line 245 "src/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st184;
 st184:
 	if ( ++p == pe )
 		goto _test_eof184;
 case 184:
-#line 3328 "src/memcached-grammar.m"
+#line 3325 "src/memcached-grammar.cc"
 	switch( (*p) ) {
 		case 32: goto st184;
 		case 78: goto st185;
@@ -3639,7 +3636,7 @@ case 196:
 	_out: {}
 	}
 
-#line 307 "src/memcached-grammar.rl"
+#line 306 "src/memcached-grammar.rl"
 
 
 	if (!done) {
@@ -3652,7 +3649,7 @@ case 196:
 			return -1;
 		}
 		char *r;
-		if ((r = memmem(p, pe - p, "\r\n", 2)) != NULL) {
+		if ((r = (char *) memmem(p, pe - p, "\r\n", 2)) != NULL) {
 			in->pos = r + 2;
 			obuf_dup(out, "CLIENT_ERROR bad command line format\r\n", 38);
 			return 1;
diff --git a/src/memcached-grammar.rl b/src/memcached-grammar.rl
index c92f04905dcd9a8985c8e8e87e6b8c1e36ceec37..d015f8a85ff5ad2eb018755ba2644c5f5ef99181 100644
--- a/src/memcached-grammar.rl
+++ b/src/memcached-grammar.rl
@@ -138,7 +138,8 @@ memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
 				value_len = load_varint32(&field);
 
 				if (is_numeric(field, value_len)) {
-					value = natoq(field, field + value_len);
+					value = natoq((const char *) field,
+						(const char *) field + value_len);
 
 					if (incr_sign > 0) {
 						value += incr;
@@ -153,20 +154,19 @@ memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
 					flags = m->flags;
 
 					b = tbuf_new(fiber->gc_pool);
-					tbuf_printf(b, "%"PRIu64, value);
+					tbuf_printf(b, "%" PRIu64, value);
 					data = b->data;
 					bytes = b->size;
 
 					stats.cmd_set++;
-					@try {
+					try {
 						store(key, exptime, flags, bytes, data);
 						stats.total_items++;
 						obuf_dup(out, b->data, b->size);
 						obuf_dup(out, "\r\n", 2);
-					}
-					@catch (ClientError *e) {
+					} catch (const ClientError& e) {
 						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e->errmsg, strlen(e->errmsg));
+						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 						obuf_dup(out, "\r\n", 2);
 					}
 				} else {
@@ -182,25 +182,25 @@ memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
 			if (tuple == NULL || expired(tuple)) {
 				obuf_dup(out, "NOT_FOUND\r\n", 11);
 			} else {
-				@try {
-					delete(key);
+				try {
+					remove(key);
 					obuf_dup(out, "DELETED\r\n", 9);
 				}
-				@catch (ClientError *e) {
+				catch (const ClientError& e) {
 					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e->errmsg, strlen(e->errmsg));
+					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 					obuf_dup(out, "\r\n", 2);
 				}
 			}
 		}
 
 		action get {
-			@try {
+			try {
 				memcached_get(out, keys_count, keys, show_cas);
-			} @catch (ClientError *e) {
+			} catch (const ClientError& e) {
 				obuf_rollback_to_svp(out, &obuf_svp);
 				obuf_dup(out, "SERVER_ERROR ", 13);
-				obuf_dup(out, e->errmsg, strlen(e->errmsg));
+				obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
 				obuf_dup(out, "\r\n", 2);
 			}
 		}
@@ -316,7 +316,7 @@ memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
 			return -1;
 		}
 		char *r;
-		if ((r = memmem(p, pe - p, "\r\n", 2)) != NULL) {
+		if ((r = (char *) memmem(p, pe - p, "\r\n", 2)) != NULL) {
 			in->pos = r + 2;
 			obuf_dup(out, "CLIENT_ERROR bad command line format\r\n", 38);
 			return 1;
diff --git a/src/memcached.m b/src/memcached.cc
similarity index 75%
rename from src/memcached.m
rename to src/memcached.cc
index fac53e681222482641b7e024c7fa1adf9f79ce7e..fb501909f005300df8f0fe5d265567c34d9b52d9 100644
--- a/src/memcached.m
+++ b/src/memcached.cc
@@ -37,13 +37,16 @@
 #include "box/port.h"
 #include "box/tuple.h"
 #include "fiber.h"
-#include "cfg/warning.h"
-#include  TARANTOOL_CONFIG
+extern "C" {
+#include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 #include "say.h"
 #include "stat.h"
 #include "salloc.h"
 #include "pickle.h"
 #include "coio_buf.h"
+#include "scoped_guard.h"
 
 #define STAT(_)					\
         _(MEMC_GET, 1)				\
@@ -85,14 +88,14 @@ tbuf_append_field(struct tbuf *b, const void *f)
 {
 	const void *begin = f;
 	u32 size = load_varint32(&f);
-	tbuf_append(b, begin, f + size - begin);
+	tbuf_append(b, begin, (const char *) f - (const char *) begin + size);
 }
 
 void
 tbuf_store_field(struct tbuf *b, const void *field, u32 len)
 {
 	char buf[sizeof(u32)+1];
-	char *bufend = pack_varint32(buf, len);
+	char *bufend = (char *) pack_varint32(buf, len);
 	tbuf_append(b, buf, bufend - buf);
 	tbuf_append(b, field, len);
 }
@@ -107,11 +110,11 @@ tbuf_read_field(struct tbuf *buf)
 	const void *field = buf->data;
 	u32 field_len = pick_varint32((const void **) &buf->data,
 				      buf->data + buf->size);
-	if (buf->data + field_len > field + buf->size)
-		tnt_raise(IllegalParams, :"packet too short (expected a field)");
+	if ((char *) buf->data + field_len > (char *) field + buf->size)
+		tnt_raise(IllegalParams, "packet too short (expected a field)");
 	buf->data += field_len;
-	buf->size -= buf->data - field;
-	buf->capacity -= buf->data - field;
+	buf->size -= (const char *) buf->data - (const char *) field;
+	buf->capacity -= (const char *) buf->data - (const char *) field;
 	return field;
 }
 
@@ -137,13 +140,13 @@ store(const void *key, u32 exptime, u32 flags, u32 bytes, const char *data)
 	tbuf_store_field(req, &m, sizeof(m));
 
 	char b[43];
-	sprintf(b, " %"PRIu32" %"PRIu32"\r\n", flags, bytes);
+	sprintf(b, " %" PRIu32 " %" PRIu32 "\r\n", flags, bytes);
 	tbuf_store_field(req, b, strlen(b));
 
 	tbuf_store_field(req, data, bytes);
 
 	int key_len = load_varint32(&key);
-	say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64,
+	say_debug("memcached/store key:(%i)'%.*s' exptime:%" PRIu32 " flags:%" PRIu32 " cas:%" PRIu64,
 		  key_len, key_len, (char*) key, exptime, flags, cas);
 	/*
 	 * Use a box dispatch wrapper which handles correctly
@@ -153,7 +156,7 @@ store(const void *key, u32 exptime, u32 flags, u32 bytes, const char *data)
 }
 
 static void
-delete(const void *key)
+remove(const void *key)
 {
 	u32 key_len = 1;
 	u32 box_flags = 0;
@@ -170,14 +173,14 @@ delete(const void *key)
 static struct tuple *
 find(const void *key)
 {
-	return [memcached_index findByKey :key :1];
+	return memcached_index->findByKey(key, 1);
 }
 
 static struct meta *
 meta(struct tuple *tuple)
 {
 	void *field = tuple_field(tuple, 1);
-	return field + 1;
+	return (struct meta *) ((char *) field + 1);
 }
 
 static bool
@@ -217,7 +220,8 @@ struct salloc_stat_memcached_cb_ctx {
 static int
 salloc_stat_memcached_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
 {
-	struct salloc_stat_memcached_cb_ctx *ctx = cb_ctx;
+	struct salloc_stat_memcached_cb_ctx *ctx =
+			(struct salloc_stat_memcached_cb_ctx *) cb_ctx;
 	ctx->bytes_used	+= cstat->bytes_used;
 	ctx->items	+= cstat->items;
 	return 0;
@@ -232,25 +236,25 @@ print_stats(struct obuf *out)
 	memstats.bytes_used = memstats.items = 0;
 	salloc_stat(salloc_stat_memcached_cb, NULL, &memstats);
 
-	tbuf_printf(buf, "STAT pid %"PRIu32"\r\n", (u32)getpid());
-	tbuf_printf(buf, "STAT uptime %"PRIu32"\r\n", (u32)tarantool_uptime());
-	tbuf_printf(buf, "STAT time %"PRIu32"\r\n", (u32)ev_now());
+	tbuf_printf(buf, "STAT pid %" PRIu32 "\r\n", (u32)getpid());
+	tbuf_printf(buf, "STAT uptime %" PRIu32 "\r\n", (u32)tarantool_uptime());
+	tbuf_printf(buf, "STAT time %" PRIu32 "\r\n", (u32)ev_now());
 	tbuf_printf(buf, "STAT version 1.2.5 (tarantool/box)\r\n");
-	tbuf_printf(buf, "STAT pointer_size %"PRI_SZ"\r\n", sizeof(void *)*8);
-	tbuf_printf(buf, "STAT curr_items %"PRIu64"\r\n", memstats.items);
-	tbuf_printf(buf, "STAT total_items %"PRIu64"\r\n", stats.total_items);
-	tbuf_printf(buf, "STAT bytes %"PRIu64"\r\n", memstats.bytes_used);
-	tbuf_printf(buf, "STAT curr_connections %"PRIu32"\r\n", stats.curr_connections);
-	tbuf_printf(buf, "STAT total_connections %"PRIu32"\r\n", stats.total_connections);
-	tbuf_printf(buf, "STAT connection_structures %"PRIu32"\r\n", stats.curr_connections); /* lie a bit */
-	tbuf_printf(buf, "STAT cmd_get %"PRIu64"\r\n", stats.cmd_get);
-	tbuf_printf(buf, "STAT cmd_set %"PRIu64"\r\n", stats.cmd_set);
-	tbuf_printf(buf, "STAT get_hits %"PRIu64"\r\n", stats.get_hits);
-	tbuf_printf(buf, "STAT get_misses %"PRIu64"\r\n", stats.get_misses);
-	tbuf_printf(buf, "STAT evictions %"PRIu64"\r\n", stats.evictions);
-	tbuf_printf(buf, "STAT bytes_read %"PRIu64"\r\n", stats.bytes_read);
-	tbuf_printf(buf, "STAT bytes_written %"PRIu64"\r\n", stats.bytes_written);
-	tbuf_printf(buf, "STAT limit_maxbytes %"PRIu64"\r\n", (u64)(cfg.slab_alloc_arena * (1 << 30)));
+	tbuf_printf(buf, "STAT pointer_size %" PRI_SZ "\r\n", sizeof(void *)*8);
+	tbuf_printf(buf, "STAT curr_items %" PRIu64 "\r\n", memstats.items);
+	tbuf_printf(buf, "STAT total_items %" PRIu64 "\r\n", stats.total_items);
+	tbuf_printf(buf, "STAT bytes %" PRIu64 "\r\n", memstats.bytes_used);
+	tbuf_printf(buf, "STAT curr_connections %" PRIu32 "\r\n", stats.curr_connections);
+	tbuf_printf(buf, "STAT total_connections %" PRIu32 "\r\n", stats.total_connections);
+	tbuf_printf(buf, "STAT connection_structures %" PRIu32 "\r\n", stats.curr_connections); /* lie a bit */
+	tbuf_printf(buf, "STAT cmd_get %" PRIu64 "\r\n", stats.cmd_get);
+	tbuf_printf(buf, "STAT cmd_set %" PRIu64 "\r\n", stats.cmd_set);
+	tbuf_printf(buf, "STAT get_hits %" PRIu64 "\r\n", stats.get_hits);
+	tbuf_printf(buf, "STAT get_misses %" PRIu64 "\r\n", stats.get_misses);
+	tbuf_printf(buf, "STAT evictions %" PRIu64 "\r\n", stats.evictions);
+	tbuf_printf(buf, "STAT bytes_read %" PRIu64 "\r\n", stats.bytes_read);
+	tbuf_printf(buf, "STAT bytes_written %" PRIu64 "\r\n", stats.bytes_written);
+	tbuf_printf(buf, "STAT limit_maxbytes %" PRIu64 "\r\n", (u64)(cfg.slab_alloc_arena * (1 << 30)));
 	tbuf_printf(buf, "STAT threads 1\r\n");
 	tbuf_printf(buf, "END\r\n");
 	obuf_dup(out, buf->data, buf->size);
@@ -261,7 +265,7 @@ void memcached_get(struct obuf *out, size_t keys_count, struct tbuf *keys,
 {
 	stat_collect(stat_base, MEMC_GET, 1);
 	stats.cmd_get++;
-	say_debug("ensuring space for %"PRI_SZ" keys", keys_count);
+	say_debug("ensuring space for %" PRI_SZ " keys", keys_count);
 	while (keys_count-- > 0) {
 		struct tuple *tuple;
 		const struct meta *m;
@@ -287,17 +291,17 @@ void memcached_get(struct obuf *out, size_t keys_count, struct tbuf *keys,
 
 		/* skip key */
 		_l = load_varint32(&field);
-		field += _l;
+		field = (const char *) field + _l;
 
 		/* metainfo */
 		_l = load_varint32(&field);
-		m = field;
-		field += _l;
+		m = (const struct meta *) field;
+		field = (const char *) field + _l;
 
 		/* suffix */
 		suffix_len = load_varint32(&field);
 		suffix = field;
-		field += suffix_len;
+		field = (const char *) field + suffix_len;
 
 		/* value */
 		value_len = load_varint32(&field);
@@ -313,7 +317,7 @@ void memcached_get(struct obuf *out, size_t keys_count, struct tbuf *keys,
 
 		if (show_cas) {
 			struct tbuf *b = tbuf_new(fiber->gc_pool);
-			tbuf_printf(b, "VALUE %.*s %"PRIu32" %"PRIu32" %"PRIu64"\r\n", key_len, (char*) key, m->flags, value_len, m->cas);
+			tbuf_printf(b, "VALUE %.*s %" PRIu32 " %" PRIu32 " %" PRIu64 "\r\n", key_len, (char*) key, m->flags, value_len, m->cas);
 			obuf_dup(out, b->data, b->size);
 			stats.bytes_written += b->size;
 		} else {
@@ -335,8 +339,8 @@ flush_all(va_list ap)
 	uintptr_t delay = va_arg(ap, uintptr_t);
 	fiber_sleep(delay - ev_now());
 	struct tuple *tuple;
-	struct iterator *it = [memcached_index allocIterator];
-	[memcached_index initIterator: it :ITER_ALL :NULL :0];
+	struct iterator *it = memcached_index->allocIterator();
+	memcached_index->initIterator(it, ITER_ALL, NULL, 0);
 	while ((tuple = it->next(it))) {
 	       meta(tuple)->exptime = 1;
 	}
@@ -349,20 +353,20 @@ do {										\
 	if (bytes > (1<<20)) {							\
 		obuf_dup(out, "SERVER_ERROR object too large for cache\r\n", 41);\
 	} else {								\
-		@try {								\
+		try {								\
 			store(key, exptime, flags, bytes, data);		\
 			stats.total_items++;					\
 			obuf_dup(out, "STORED\r\n", 8);				\
 		}								\
-		@catch (ClientError *e) {					\
+		catch (const ClientError& e) {					\
 			obuf_dup(out, "SERVER_ERROR ", 13);			\
-			obuf_dup(out, e->errmsg, strlen(e->errmsg));		\
+			obuf_dup(out, e.errmsg(), strlen(e.errmsg()));		\
 			obuf_dup(out, "\r\n", 2);				\
 		}								\
 	}									\
 } while (0)
 
-#include "memcached-grammar.m"
+#include "memcached-grammar.cc"
 
 void
 memcached_loop(struct ev_io *coio, struct iobuf *iobuf)
@@ -413,18 +417,20 @@ memcached_handler(va_list ap)
 	stats.total_connections++;
 	stats.curr_connections++;
 
-	@try {
+	try {
+		auto scoped_guard = make_scoped_guard([&] {
+			fiber_sleep(0.01);
+			stats.curr_connections--;
+			evio_close(&coio);
+			iobuf_delete(iobuf);
+		});
+
 		memcached_loop(&coio, iobuf);
 		iobuf_flush(iobuf, &coio);
-	} @catch (FiberCancelException *e) {
-		@throw;
-	} @catch (tnt_Exception *e) {
-		[e log];
-	} @finally {
-		fiber_sleep(0.01);
-		stats.curr_connections--;
-		evio_close(&coio);
-		iobuf_delete(iobuf);
+	} catch (const FiberCancelException& e) {
+		throw;
+	} catch (const Exception& e) {
+		e.log();
 	}
 }
 
@@ -437,7 +443,7 @@ memcached_check_config(struct tarantool_cfg *conf)
 
 	if (conf->memcached_port <= 0 || conf->memcached_port >= USHRT_MAX) {
 		/* invalid space number */
-		out_warning(0, "invalid memcached port value: %i",
+		out_warning(CNF_OK, "invalid memcached port value: %i",
 			    conf->memcached_port);
 		return -1;
 	}
@@ -446,14 +452,14 @@ memcached_check_config(struct tarantool_cfg *conf)
 
 	if (conf->memcached_expire_per_loop <= 0) {
 		/* invalid expire per loop value */
-		out_warning(0, "invalid expire per loop value: %i",
+		out_warning(CNF_OK, "invalid expire per loop value: %i",
 			    conf->memcached_expire_per_loop);
 		return -1;
 	}
 
 	if (conf->memcached_expire_full_sweep <= 0) {
 		/* invalid expire full sweep value */
-		out_warning(0, "invalid expire full sweep value: %i",
+		out_warning(CNF_OK, "invalid expire full sweep value: %i",
 			    conf->memcached_expire_full_sweep);
 		return -1;
 	}
@@ -498,13 +504,13 @@ memcached_space_init()
 
 
 	/* Configure memcached index key. */
-	struct key_def *key_def = malloc(sizeof(struct key_def));
+	struct key_def *key_def = (struct key_def *) malloc(sizeof(struct key_def));
 	key_def->part_count = 1;
 	key_def->is_unique = true;
 	key_def->type = HASH;
 
-	key_def->parts = malloc(sizeof(struct key_part));
-	key_def->cmp_order = malloc(sizeof(u32));
+	key_def->parts = (struct key_part *) malloc(sizeof(struct key_part));
+	key_def->cmp_order = (u32 *) malloc(sizeof(u32));
 
 	if (key_def->parts == NULL || key_def->cmp_order == NULL)
 		panic("out of memory when configuring memcached_space");
@@ -519,10 +525,8 @@ memcached_space_init()
 	struct space *memc_s =
 		space_create(cfg.memcached_space, key_def, 1, 4);
 
-	Index *memc_index = [Index alloc: HASH :key_def :memc_s];
+	Index *memc_index = Index::factory(HASH, key_def, memc_s);
 	space_set_index(memc_s, 0, memc_index);
-
-	[memc_index init: key_def :memc_s];
 }
 
 /** Delete a bunch of expired keys. */
@@ -533,13 +537,13 @@ memcached_delete_expired_keys(struct tbuf *keys_to_delete)
 	int expired_keys = 0;
 
 	while (keys_to_delete->size > 0) {
-		@try {
-			delete(tbuf_read_field(keys_to_delete));
+		try {
+			remove(tbuf_read_field(keys_to_delete));
 			expired_keys++;
 		}
-		@catch (ClientError *e) {
+		catch (const ClientError& e) {
 			/* expire is off when replication is on */
-			assert(e->errcode != ER_NONMASTER);
+			assert(e.errcode() != ER_NONMASTER);
 			/* The error is already logged. */
 		}
 	}
@@ -547,7 +551,7 @@ memcached_delete_expired_keys(struct tbuf *keys_to_delete)
 
 	double delay = ((double) cfg.memcached_expire_per_loop *
 			cfg.memcached_expire_full_sweep /
-			([memcached_index size] + 1));
+			(memcached_index->size() + 1));
 	if (delay > 1)
 		delay = 1;
 	fiber_setcancellable(true);
@@ -561,11 +565,11 @@ memcached_expire_loop(va_list ap __attribute__((unused)))
 	struct tuple *tuple = NULL;
 
 	say_info("memcached expire fiber started");
-	memcached_it = [memcached_index allocIterator];
-	@try {
+	memcached_it = memcached_index->allocIterator();
+	try {
 restart:
 		if (tuple == NULL)
-			[memcached_index initIterator: memcached_it :ITER_ALL :NULL :0];
+			memcached_index->initIterator(memcached_it, ITER_ALL, NULL, 0);
 
 		struct tbuf *keys_to_delete = tbuf_new(fiber->gc_pool);
 
@@ -585,7 +589,7 @@ memcached_expire_loop(va_list ap __attribute__((unused)))
 		memcached_delete_expired_keys(keys_to_delete);
 		fiber_gc();
 		goto restart;
-	} @finally {
+	} catch(const Exception& e) {
 		memcached_it->free(memcached_it);
 		memcached_it = NULL;
 	}
@@ -597,10 +601,10 @@ void memcached_start_expire()
 		return;
 
 	assert(memcached_expire == NULL);
-	@try {
+	try {
 		memcached_expire = fiber_new("memcached_expire",
 						memcached_expire_loop);
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& e) {
 		say_error("can't start the expire fiber");
 		return;
 	}
diff --git a/src/object.m b/src/object.cc
similarity index 83%
rename from src/object.m
rename to src/object.cc
index 7d5a6c3bb278c62749c2b95c8764327eb48303be..0f79a1b654f27e0eb12bad13e40304652e43dc88 100644
--- a/src/object.m
+++ b/src/object.cc
@@ -26,26 +26,5 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#import "object.h"
-#include <stdlib.h>
 
-@implementation tnt_Object
-+ (id) alloc
-{
-	return class_createInstance(self, 0);
-}
-- (id) init
-{
-	return self;
-}
-- (void) subclassResponsibility: (SEL) cmd
-{
-	(void) cmd;
-	abort();
-}
-
-- (void) free
-{
-	object_dispose(self);
-}
-@end
+#include "object.h"
diff --git a/src/opts.c b/src/opts.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b02f1d68d3736dcd666ef404b4e58c1b9f026b1
--- /dev/null
+++ b/src/opts.c
@@ -0,0 +1,57 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tarantool.h"
+
+#include <stddef.h>
+
+#include <third_party/gopt/gopt.h>
+
+const void *opt_def =
+	gopt_start(gopt_option('g', GOPT_ARG, gopt_shorts(0),
+			       gopt_longs("cfg-get", "cfg_get"),
+			       "=KEY", "return a value from configuration file described by KEY"),
+		   gopt_option('k', 0, gopt_shorts(0),
+			       gopt_longs("check-config"),
+			       NULL, "Check configuration file for errors"),
+		   gopt_option('c', GOPT_ARG, gopt_shorts('c'),
+			       gopt_longs("config"),
+			       "=FILE", "path to configuration file (default: " DEFAULT_CFG_FILENAME ")"),
+		   gopt_option('I', 0, gopt_shorts(0),
+			       gopt_longs("init-storage", "init_storage"),
+			       NULL, "initialize storage (an empty snapshot file) and exit"),
+		   gopt_option('v', 0, gopt_shorts('v'), gopt_longs("verbose"),
+			       NULL, "increase verbosity level in log messages"),
+		   gopt_option('B', 0, gopt_shorts('B'), gopt_longs("background"),
+			       NULL, "redirect input/output streams to a log file and run as daemon"),
+		   gopt_option('h', 0, gopt_shorts('h', '?'), gopt_longs("help"),
+			       NULL, "display this help and exit"),
+		   gopt_option('V', 0, gopt_shorts('V'), gopt_longs("version"),
+			       NULL, "print program version and exit")
+);
diff --git a/src/palloc.m b/src/palloc.cc
similarity index 77%
rename from src/palloc.m
rename to src/palloc.cc
index 2d7831026e8968995cd313da8aee0a4caa56605c..1a35530fee38b9c58227f302f2904c94e7ac1520 100644
--- a/src/palloc.m
+++ b/src/palloc.cc
@@ -48,7 +48,7 @@ struct chunk {
 	size_t free;
 	size_t size;
 
-	struct chunk_class *class;
+	struct chunk_class *clazz;
 	SLIST_ENTRY(chunk) busy_link;
 	SLIST_ENTRY(chunk) free_link;
 };
@@ -100,25 +100,25 @@ palloc_greatest_size(void)
 static struct chunk_class *
 class_init(size_t size)
 {
-	struct chunk_class *class;
+	struct chunk_class *clazz;
 
-	class = malloc(sizeof(struct chunk_class));
-	if (class == NULL)
+	clazz = (struct chunk_class *) malloc(sizeof(struct chunk_class));
+	if (clazz == NULL)
 		return NULL;
 
-	class->i = class_count++;
-	class->chunks_count = 0;
-	class->allocated_size = size;
-	SLIST_INIT(&class->chunks);
-	TAILQ_INSERT_TAIL(&classes, class, link);
+	clazz->i = class_count++;
+	clazz->chunks_count = 0;
+	clazz->allocated_size = size;
+	SLIST_INIT(&clazz->chunks);
+	TAILQ_INSERT_TAIL(&classes, clazz, link);
 
-	return class;
+	return clazz;
 }
 
 int
 palloc_init(void)
 {
-	struct chunk_class *class;
+	struct chunk_class *clazz;
 
 	class_count = 0;
 	TAILQ_INIT(&classes);
@@ -137,10 +137,10 @@ palloc_init(void)
 	if (class_init(palloc_greatest_size()) == NULL)
 		return 0;
 
-	if ((class = class_init(-1)) == NULL)
+	if ((clazz = class_init(-1)) == NULL)
 		return 0;
 
-	TAILQ_NEXT(class, link) = NULL;
+	TAILQ_NEXT(clazz, link) = NULL;
 
 	eter_pool = palloc_create_pool("eter_pool");
 	return 1;
@@ -155,9 +155,9 @@ palloc_free(void)
 
 	palloc_free_unused();
 
-	struct chunk_class *class, *class_next;
-	TAILQ_FOREACH_SAFE(class, &classes, link, class_next)
-		free(class);
+	struct chunk_class *clazz, *class_next;
+	TAILQ_FOREACH_SAFE(clazz, &classes, link, class_next)
+		free(clazz);
 }
 
 static void
@@ -174,47 +174,47 @@ static struct chunk *
 next_chunk_for(struct palloc_pool *restrict pool, size_t size)
 {
 	struct chunk *restrict chunk = SLIST_FIRST(&pool->chunks);
-	struct chunk_class *restrict class;
+	struct chunk_class *restrict clazz;
 	size_t chunk_size;
 
 	if (chunk != NULL)
-		class = chunk->class;
+		clazz = chunk->clazz;
 	else
-		class = TAILQ_FIRST(&classes);
+		clazz = TAILQ_FIRST(&classes);
 
-	if (class->allocated_size == -1)
-		class = TAILQ_PREV(class, class_tailq_head, link);
+	if (clazz->allocated_size == -1)
+		clazz = TAILQ_PREV(clazz, class_tailq_head, link);
 
-	while (class != NULL && class->allocated_size < size + sizeof(struct chunk))
-		class = TAILQ_NEXT(class, link);
+	while (clazz != NULL && clazz->allocated_size < size + sizeof(struct chunk))
+		clazz = TAILQ_NEXT(clazz, link);
 
-	assert(class != NULL);
+	assert(clazz != NULL);
 
-	chunk = SLIST_FIRST(&class->chunks);
+	chunk = SLIST_FIRST(&clazz->chunks);
 	if (chunk != NULL) {
-		SLIST_REMOVE_HEAD(&class->chunks, free_link);
+		SLIST_REMOVE_HEAD(&clazz->chunks, free_link);
 		goto found;
 	}
 
 	if (size > palloc_greatest_size()) {
 		chunk_size = size + sizeof(struct chunk);
-		chunk = malloc(chunk_size);
+		chunk = (struct chunk *) malloc(chunk_size);
 		if (chunk == NULL)
 			return NULL;
 	} else {
-		chunk_size = class->allocated_size;
-		chunk = mmap(NULL, chunk_size,
+		chunk_size = clazz->allocated_size;
+		chunk = (struct chunk *) mmap(NULL, chunk_size,
 			     PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 		if (chunk == MAP_FAILED)
 			return NULL;
 	}
 
-	class->chunks_count++;
+	clazz->chunks_count++;
 	chunk->magic = chunk_magic;
 	chunk->size = chunk_size;
 	chunk->free = chunk_size - sizeof(struct chunk);
-	chunk->brk = (void *)chunk + sizeof(struct chunk);
-	chunk->class = class;
+	chunk->brk = (char *)chunk + sizeof(struct chunk);
+	chunk->clazz = clazz;
       found:
 	assert(chunk != NULL && chunk->magic == chunk_magic);
 	SLIST_INSERT_HEAD(&pool->chunks, chunk, busy_link);
@@ -244,13 +244,13 @@ palloc_slow_path(struct palloc_pool *restrict pool, size_t size)
 	struct chunk *chunk;
 	chunk = next_chunk_for(pool, size);
 	if (chunk == NULL) {
-		tnt_raise(LoggedError, :ER_MEMORY_ISSUE,
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
 			  size, "palloc", "next chunk");
 	}
 
 	assert(chunk->free >= size);
 	void *ptr = chunk->brk;
-	chunk->brk += size;
+	chunk->brk = (char *) chunk->brk + size;
 	chunk->free -= size;
 	return ptr;
 }
@@ -266,15 +266,15 @@ palloc(struct palloc_pool *restrict pool, size_t size)
 
 	if (likely(chunk != NULL && chunk->free >= rz_size)) {
 		ptr = chunk->brk;
-		chunk->brk += rz_size;
+		chunk->brk = (char *) chunk->brk + rz_size;
 		chunk->free -= rz_size;
 	} else
 		ptr = palloc_slow_path(pool, rz_size);
 
-	assert(poisoned(ptr + PALLOC_REDZONE, size) == NULL);
-	(void) VALGRIND_MAKE_MEM_DEFINED(ptr + PALLOC_REDZONE, size);
+	assert(poisoned((char *) ptr + PALLOC_REDZONE, size) == NULL);
+	(void) VALGRIND_MAKE_MEM_DEFINED((char *) ptr + PALLOC_REDZONE, size);
 
-	return ptr + PALLOC_REDZONE;
+	return (char *) ptr + PALLOC_REDZONE;
 }
 
 void *__attribute__((regparm(2)))
@@ -302,8 +302,8 @@ chunk_free(struct chunk *chunk)
 {
 	if (chunk->size <= palloc_greatest_size()) {
 		chunk->free = chunk->size - sizeof(struct chunk);
-		chunk->brk = (void *)chunk + sizeof(struct chunk);
-		SLIST_INSERT_HEAD(&chunk->class->chunks, chunk, free_link);
+		chunk->brk = (char *)chunk + sizeof(struct chunk);
+		SLIST_INSERT_HEAD(&chunk->clazz->chunks, chunk, free_link);
 		poison_chunk(chunk);
 	} else {
 		free(chunk);
@@ -328,7 +328,7 @@ ptruncate(struct palloc_pool *pool, size_t new_size)
 				     sizeof(struct chunk));
 		if (chunk_used > cut_size) {
 			/* This is the last chunk to trim. */
-			chunk->brk -= cut_size;
+			chunk->brk = (char *) chunk->brk - cut_size;
 			chunk->free += cut_size;
 			(void) VALGRIND_MAKE_MEM_NOACCESS(chunk->brk, cut_size);
 			cut_size = 0;
@@ -365,7 +365,7 @@ palloc_reset(struct palloc_pool *pool)
 		pool->allocated -= chunk->size - sizeof(struct chunk) -
 				   chunk->free;
 		chunk->free = chunk->size - sizeof(struct chunk);
-		chunk->brk = (void *)chunk + sizeof(struct chunk);
+		chunk->brk = (char *)chunk + sizeof(struct chunk);
 	}
 }
 
@@ -379,9 +379,10 @@ prelease_after(struct palloc_pool *pool, size_t after)
 struct palloc_pool *
 palloc_create_pool(const char *name)
 {
-	struct palloc_pool *pool = calloc(sizeof(struct palloc_pool), 1);
+	struct palloc_pool *pool = (struct palloc_pool *)
+			calloc(sizeof(struct palloc_pool), 1);
 	if (pool == NULL) {
-		tnt_raise(LoggedError, :ER_MEMORY_ISSUE,
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
 			  sizeof(struct palloc_pool),
 			  "malloc", "palloc pool");
 	}
@@ -402,20 +403,20 @@ palloc_destroy_pool(struct palloc_pool *pool)
 void
 palloc_free_unused(void)
 {
-	struct chunk_class *class;
+	struct chunk_class *clazz;
 	struct chunk *chunk, *next_chunk;
 
-	TAILQ_FOREACH(class, &classes, link) {
-		SLIST_FOREACH_SAFE(chunk, &class->chunks, free_link, next_chunk)
-			munmap(chunk, class->allocated_size);
-		SLIST_INIT(&class->chunks);
+	TAILQ_FOREACH(clazz, &classes, link) {
+		SLIST_FOREACH_SAFE(chunk, &clazz->chunks, free_link, next_chunk)
+			munmap(chunk, clazz->allocated_size);
+		SLIST_INIT(&clazz->chunks);
 	}
 }
 
 void
 palloc_stat(struct tbuf *buf)
 {
-	struct chunk_class *class;
+	struct chunk_class *clazz;
 	struct chunk *chunk;
 	struct palloc_pool *pool;
 	int chunks[class_count];
@@ -433,26 +434,26 @@ palloc_stat(struct tbuf *buf)
 			tbuf_printf(buf, "      busy chunks:" CRLF);
 
 			SLIST_FOREACH(chunk, &pool->chunks, busy_link)
-			    chunks[chunk->class->i]++;
+			    chunks[chunk->clazz->i]++;
 
-			TAILQ_FOREACH(class, &classes, link) {
-				if (chunks[class->i] == 0)
+			TAILQ_FOREACH(clazz, &classes, link) {
+				if (chunks[clazz->i] == 0)
 					continue;
-				tbuf_printf(buf, "        - { size: %"PRIu32", used: %i }" CRLF,
-					    class->allocated_size, chunks[class->i]);
+				tbuf_printf(buf, "        - { size: %" PRIu32 ", used: %i }" CRLF,
+					    clazz->allocated_size, chunks[clazz->i]);
 			}
 		}
 	}
 	tbuf_printf(buf, "  classes:" CRLF);
-	TAILQ_FOREACH(class, &classes, link) {
+	TAILQ_FOREACH(clazz, &classes, link) {
 		int free_chunks = 0;
-		SLIST_FOREACH(chunk, &class->chunks, free_link)
+		SLIST_FOREACH(chunk, &clazz->chunks, free_link)
 			free_chunks++;
 
 		tbuf_printf(buf,
-			    "    - { size: %"PRIu32
-			    ", free_chunks: %- 6i, busy_chunks: %- 6i }" CRLF, class->allocated_size,
-			    free_chunks, class->chunks_count - free_chunks);
+			    "    - { size: %" PRIu32
+			    ", free_chunks: %- 6i, busy_chunks: %- 6i }" CRLF, clazz->allocated_size,
+			    free_chunks, clazz->chunks_count - free_chunks);
 	}
 	u64 palloc_total = 0;
 	u64 palloc_used = 0;
@@ -465,7 +466,7 @@ palloc_stat(struct tbuf *buf)
 			palloc_total += chunk->size;
 	}
 	tbuf_printf(buf, "  total:" CRLF);
-	tbuf_printf(buf, "    - { occupied: %"PRIu64", used: %"PRIu64" }"CRLF,
+	tbuf_printf(buf, "    - { occupied: %" PRIu64 ", used: %" PRIu64 " }" CRLF,
 		    palloc_total, palloc_used);
 
 }
diff --git a/src/pickle.m b/src/pickle.cc
similarity index 99%
rename from src/pickle.m
rename to src/pickle.cc
index 09aaf354321c0fcd16ed871c0164271c32924f2a..428602ededc4033269fbb54c5a5be44c697c855b 100644
--- a/src/pickle.m
+++ b/src/pickle.cc
@@ -27,3 +27,4 @@
  * SUCH DAMAGE.
  */
 #include "pickle.h"
+
diff --git a/src/recovery.m b/src/recovery.cc
similarity index 97%
rename from src/recovery.m
rename to src/recovery.cc
index dba5f7004b5d94ec7f6eee11dc8e81eeab24da48..240e5c6547a76ce5bef37d6c36960681559975c2 100644
--- a/src/recovery.m
+++ b/src/recovery.cc
@@ -119,8 +119,9 @@ wait_lsn_set(struct wait_lsn *wait_lsn, int64_t lsn)
 static inline void
 wakeup_lsn_waiter(struct recovery_state *r)
 {
-	if (r->wait_lsn.waiter && r->confirmed_lsn >= r->wait_lsn.lsn)
+	if (r->wait_lsn.waiter && r->confirmed_lsn >= r->wait_lsn.lsn) {
 		fiber_wakeup(r->wait_lsn.waiter);
+	}
 }
 
 void
@@ -167,10 +168,12 @@ recovery_wait_lsn(struct recovery_state *r, int64_t lsn)
 {
 	while (lsn < r->confirmed_lsn) {
 		wait_lsn_set(&r->wait_lsn, lsn);
-		@try {
+		try {
 			fiber_yield();
-		} @finally {
 			wait_lsn_clear(&r->wait_lsn);
+		} catch(const Exception& e) {
+			wait_lsn_clear(&r->wait_lsn);
+			throw;
 		}
 	}
 }
@@ -202,7 +205,7 @@ recovery_init(const char *snap_dirname, const char *wal_dirname,
 	      int rows_per_wal, int flags)
 {
 	assert(recovery_state == NULL);
-	recovery_state = p0alloc(eter_pool, sizeof(struct recovery_state));
+	recovery_state = (struct recovery_state *) p0alloc(eter_pool, sizeof(struct recovery_state));
 	struct recovery_state *r = recovery_state;
 	recovery_update_mode(r, "none", 0);
 
@@ -226,7 +229,7 @@ void
 recovery_update_mode(struct recovery_state *r,
 		     const char *mode, double fsync_delay)
 {
-	r->wal_mode = strindex(wal_mode_STRS, mode, WAL_MODE_MAX);
+	r->wal_mode = (enum wal_mode) strindex(wal_mode_STRS, mode, WAL_MODE_MAX);
 	assert(r->wal_mode != WAL_MODE_MAX);
 	/* No mutex lock: let's not bother with whether
 	 * or not a WAL writer thread is present, and
@@ -384,6 +387,9 @@ recover_remaining_wals(struct recovery_state *r)
 	struct log_io *next_wal;
 	i64 current_lsn, wal_greatest_lsn;
 	size_t rows_before;
+	FILE *f;
+	char *filename;
+	enum log_suffix suffix;
 
 	current_lsn = r->confirmed_lsn + 1;
 	wal_greatest_lsn = greatest_lsn(r->wal_dir);
@@ -418,9 +424,8 @@ recover_remaining_wals(struct recovery_state *r)
 		 * .xlog, with no risk of a concurrent
 		 * inprogress_log_rename().
 		 */
-		FILE *f = NULL;
-		char *filename;
-		enum log_suffix suffix = INPROGRESS;
+		f = NULL;
+		suffix = INPROGRESS;
 		if (current_lsn == wal_greatest_lsn) {
 			/* Last WAL present at the time of rescan. */
 			filename = format_filename(r->wal_dir,
@@ -607,7 +612,7 @@ recovery_stop_file(struct wal_watcher *watcher)
 static void
 recovery_rescan_dir(ev_timer *w, int revents __attribute__((unused)))
 {
-	struct recovery_state *r = w->data;
+	struct recovery_state *r = (struct recovery_state *) w->data;
 	struct wal_watcher *watcher = r->watcher;
 	struct log_io *save_current_wal = r->current_wal;
 
@@ -625,7 +630,7 @@ recovery_rescan_dir(ev_timer *w, int revents __attribute__((unused)))
 static void
 recovery_rescan_file(ev_stat *w, int revents __attribute__((unused)))
 {
-	struct recovery_state *r = w->data;
+	struct recovery_state *r = (struct recovery_state *) w->data;
 	struct wal_watcher *watcher = r->watcher;
 	int result = recover_wal(r, r->current_wal);
 	if (result < 0)
@@ -767,9 +772,9 @@ wal_schedule_queue(struct wal_fifo *queue)
 }
 
 static void
-wal_schedule(ev_watcher *watcher, int event __attribute__((unused)))
+wal_schedule(ev_async *watcher, int event __attribute__((unused)))
 {
-	struct wal_writer *writer = watcher->data;
+	struct wal_writer *writer = (struct wal_writer *) watcher->data;
 	struct wal_fifo commit = STAILQ_HEAD_INITIALIZER(commit);
 	struct wal_fifo rollback = STAILQ_HEAD_INITIALIZER(rollback);
 
@@ -818,7 +823,7 @@ wal_writer_init(struct wal_writer *writer)
 	STAILQ_INIT(&writer->input);
 	STAILQ_INIT(&writer->commit);
 
-	ev_async_init(&writer->write_event, (void *)wal_schedule);
+	ev_async_init(&writer->write_event, wal_schedule);
 	writer->write_event.data = writer;
 
 	(void) tt_pthread_once(&wal_writer_once, wal_writer_init_once);
@@ -1059,7 +1064,7 @@ wal_write_to_disk(struct recovery_state *r, struct wal_writer *writer,
 static void *
 wal_writer_thread(void *worker_args)
 {
-	struct recovery_state *r = worker_args;
+	struct recovery_state *r = (struct recovery_state *) worker_args;
 	struct wal_writer *writer = r->writer;
 	struct wal_fifo input = STAILQ_HEAD_INITIALIZER(input);
 	struct wal_fifo commit = STAILQ_HEAD_INITIALIZER(commit);
@@ -1109,7 +1114,7 @@ wal_write(struct recovery_state *r, i64 lsn, u64 cookie,
 
 	struct wal_writer *writer = r->writer;
 
-	struct wal_write_request *req =
+	struct wal_write_request *req = (struct wal_write_request *)
 		palloc(fiber->gc_pool, sizeof(struct wal_write_request) +
 		       sizeof(op) + row_len);
 
@@ -1158,7 +1163,7 @@ snapshot_write_row(struct log_io *l, struct fio_batch *batch,
 	ev_tstamp elapsed;
 	static ev_tstamp last = 0;
 
-	struct row_v11 *row = palloc(fiber->gc_pool,
+	struct row_v11 *row = (struct row_v11 *) palloc(fiber->gc_pool,
 				     sizeof(struct row_v11) +
 				     data_len + metadata_len);
 
diff --git a/src/replica.m b/src/replica.cc
similarity index 93%
rename from src/replica.m
rename to src/replica.cc
index be4af6d7df85356f40421784b4662a87ce750c90..753c82be2a074855b700156b2511c4d1156610f3 100644
--- a/src/replica.m
+++ b/src/replica.cc
@@ -58,10 +58,12 @@ remote_read_row(struct ev_io *coio, struct iobuf *iobuf)
 	if (to_read > 0)
 		coio_breadn(coio, in, to_read);
 
-	struct tbuf row = {
-		.size = request_len, .capacity = request_len,
-		.data = in->pos, .pool = fiber->gc_pool
-	};
+	struct tbuf row;
+	row.size = (uint32_t) request_len;
+	row.capacity = (uint32_t) request_len;
+	row.data = in->pos;
+	row.pool = fiber->gc_pool;
+
 	in->pos += request_len;
 	return row;
 }
@@ -83,7 +85,7 @@ remote_connect(struct ev_io *coio, struct sockaddr_in *remote_addr,
 	coio_readn(coio, &version, sizeof(version));
 	*err = NULL;
 	if (version != default_version)
-		tnt_raise(SystemError, :"remote version mismatch");
+		tnt_raise(IllegalParams, "remote version mismatch");
 
 	say_crit("successfully connected to master");
 	say_crit("starting replication from lsn: %" PRIi64, initial_lsn);
@@ -102,7 +104,7 @@ pull_from_remote(va_list ap)
 
 	for (;;) {
 		const char *err = NULL;
-		@try {
+		try {
 			fiber_setcancellable(true);
 			if (! evio_is_active(&coio)) {
 				if (iobuf == NULL)
@@ -123,12 +125,12 @@ pull_from_remote(va_list ap)
 
 			iobuf_gc(iobuf);
 			fiber_gc();
-		} @catch (FiberCancelException *e) {
+		} catch (const FiberCancelException& e) {
 			iobuf_delete(iobuf);
 			evio_close(&coio);
-			@throw;
-		} @catch (tnt_Exception *e) {
-			[e log];
+			throw;
+		} catch (const Exception& e) {
+			e.log();
 			if (! warning_said) {
 				if (err != NULL)
 					say_info("%s", err);
@@ -169,9 +171,9 @@ recovery_follow_remote(struct recovery_state *r, const char *addr)
 	say_crit("initializing the replica, WAL master %s", addr);
 	snprintf(name, sizeof(name), "replica/%s", addr);
 
-	@try {
+	try {
 		f = fiber_new(name, pull_from_remote);
-	} @catch (tnt_Exception *e) {
+	} catch (const Exception& ) {
 		return;
 	}
 
diff --git a/src/replication.m b/src/replication.cc
similarity index 97%
rename from src/replication.m
rename to src/replication.cc
index bb4419aebd99ec3a223ea8c679be7ab99d301664..50241c361bc3690c0f2afe71f1239fec76ed2e7c 100644
--- a/src/replication.m
+++ b/src/replication.cc
@@ -29,7 +29,10 @@
 #include <replication.h>
 #include <say.h>
 #include <fiber.h>
-#include TARANTOOL_CONFIG
+extern "C" {
+#include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 #include <palloc.h>
 #include <stddef.h>
 
@@ -151,7 +154,7 @@ replication_check_config(struct tarantool_cfg *config)
 {
 	if (config->replication_port < 0 ||
 	    config->replication_port >= USHRT_MAX) {
-		say_error("invalid replication port value: %"PRId32,
+		say_error("invalid replication port value: %" PRId32,
 			  config->replication_port);
 		return -1;
 	}
@@ -236,7 +239,7 @@ replication_on_accept(struct evio_service *service __attribute__((unused)),
          */
 	sio_setfl(fd, O_NONBLOCK, 0);
 
-	struct ev_io *io = malloc(sizeof(struct ev_io));
+	struct ev_io *io = (struct ev_io *) malloc(sizeof(struct ev_io));
 	if (io == NULL) {
 		close(fd);
 		return;
@@ -487,7 +490,7 @@ spawner_shutdown_children()
 	/* We'll wait for children no longer than 5 sec.  */
 	alarm(5);
 
-	say_info("sending signal %d to %"PRIu32" children", kill_signo,
+	say_info("sending signal %d to %" PRIu32 " children", kill_signo,
 		 (u32) spawner.child_count);
 
 	kill(0, kill_signo);
@@ -556,7 +559,7 @@ static int
 replication_relay_send_row(void *param, struct tbuf *t)
 {
 	int client_sock = (int) (intptr_t) param;
-	u8 *data = t->data;
+	u8 *data = (u8 *) t->data;
 	ssize_t bytes, len = t->size;
 	while (len > 0) {
 		bytes = write(client_sock, data, len);
@@ -624,7 +627,7 @@ replication_relay_loop(int client_sock)
 		}
 		panic("invalid LSN request size: %zu", r);
 	}
-	say_info("starting replication from lsn: %"PRIi64, lsn);
+	say_info("starting replication from lsn: %" PRIi64, lsn);
 
 	ver = tbuf_new(fiber->gc_pool);
 	tbuf_append(ver, &default_version, sizeof(default_version));
diff --git a/src/salloc.m b/src/salloc.cc
similarity index 89%
rename from src/salloc.m
rename to src/salloc.cc
index 13d18e898719de258c279ee59fbc20467bf027ba..1ba9876f1b9f3a83beeeb4b37e2da779e69f519b 100644
--- a/src/salloc.m
+++ b/src/salloc.cc
@@ -102,7 +102,7 @@ static struct arena arena;
 static struct slab *
 slab_header(void *ptr)
 {
-	struct slab *slab = SLAB_ALIGN_PTR(ptr);
+	struct slab *slab = (struct slab *) SLAB_ALIGN_PTR(ptr);
 	assert(slab->magic == SLAB_MAGIC);
 	return slab;
 }
@@ -196,7 +196,7 @@ format_slab(struct slab_cache *cache, struct slab *slab)
 	slab->cache = cache;
 	slab->items = 0;
 	slab->used = 0;
-	slab->brk = (void *)CACHEALIGN((void *)slab + sizeof(struct slab));
+	slab->brk = (char *)CACHEALIGN((char *)slab + sizeof(struct slab));
 
 	TAILQ_INSERT_HEAD(&cache->slabs, slab, cache_link);
 	TAILQ_INSERT_HEAD(&cache->free_slabs, slab, cache_free_link);
@@ -205,7 +205,7 @@ format_slab(struct slab_cache *cache, struct slab *slab)
 static bool
 fully_formatted(struct slab *slab)
 {
-	return slab->brk + slab->cache->item_size >= (void *)slab + SLAB_SIZE;
+	return (char *) slab->brk + slab->cache->item_size >= (char *)slab + SLAB_SIZE;
 }
 
 void
@@ -251,7 +251,7 @@ slab_of(struct slab_cache *cache)
 		return slab;
 	}
 
-	if ((slab = arena_alloc(&arena)) != NULL) {
+	if ((slab = (struct slab *) arena_alloc(&arena)) != NULL) {
 		format_slab(cache, slab);
 		SLIST_INSERT_HEAD(&arena.slabs, slab, link);
 		return slab;
@@ -264,8 +264,8 @@ slab_of(struct slab_cache *cache)
 static bool
 valid_item(struct slab *slab, void *item)
 {
-	return (void *)item >= (void *)(slab) + sizeof(struct slab) &&
-	    (void *)item < (void *)(slab) + sizeof(struct slab) + SLAB_SIZE;
+	return (char *)item >= (char *)(slab) + sizeof(struct slab) &&
+	    (char *)item < (char *)(slab) + sizeof(struct slab) + SLAB_SIZE;
 }
 #endif
 
@@ -279,15 +279,15 @@ salloc(size_t size, const char *what)
 	if ((cache = cache_for(size)) == NULL ||
 	    (slab = slab_of(cache)) == NULL) {
 
-		tnt_raise(LoggedError, :ER_MEMORY_ISSUE, size,
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE, size,
 			  "slab allocator", what);
 	}
 
 	if (slab->free == NULL) {
 		assert(valid_item(slab, slab->brk));
-		item = slab->brk;
-		memcpy((void *)item + cache->item_size, red_zone, sizeof(red_zone));
-		slab->brk += cache->item_size + sizeof(red_zone);
+		item = (struct slab_item *) slab->brk;
+		memcpy((char *)item + cache->item_size, red_zone, sizeof(red_zone));
+		slab->brk = (char *) slab->brk + cache->item_size + sizeof(red_zone);
 	} else {
 		assert(valid_item(slab, slab->free));
 		item = slab->free;
@@ -314,7 +314,7 @@ sfree(void *ptr)
 		return;
 	struct slab *slab = slab_header(ptr);
 	struct slab_cache *cache = slab->cache;
-	struct slab_item *item = ptr;
+	struct slab_item *item = (struct slab_item *) ptr;
 
 	if (fully_formatted(slab) && slab->free == NULL)
 		TAILQ_INSERT_TAIL(&cache->free_slabs, slab, cache_free_link);
@@ -341,17 +341,17 @@ size_t
 salloc_ptr_to_index(void *ptr)
 {
 	struct slab *slab = slab_header(ptr);
-	struct slab_item *item = ptr;
+	struct slab_item *item = (struct slab_item *) ptr;
 	struct slab_cache *clazz = slab->cache;
 
 	(void) item;
 	assert(valid_item(slab, item));
 
-	void *brk_start = (void *)CACHEALIGN((void *)slab+sizeof(struct slab));
-	ptrdiff_t item_no = (ptr - brk_start) / clazz->item_size;
+	void *brk_start = (char *)CACHEALIGN((char *)slab+sizeof(struct slab));
+	ptrdiff_t item_no = ((const char *) ptr - (const char *) brk_start) / clazz->item_size;
 	assert(item_no >= 0);
 
-	ptrdiff_t slab_no = ((void *) slab - (void *) arena.base) / SLAB_SIZE;
+	ptrdiff_t slab_no = ((const char *) slab - (const char *) arena.base) / SLAB_SIZE;
 	assert(slab_no >= 0);
 
 	size_t index = (size_t)slab_no * MAX_SLAB_ITEM_COUNT + (size_t) item_no;
@@ -371,8 +371,8 @@ salloc_ptr_from_index(size_t index)
 		(void *) ((size_t) arena.base + SLAB_SIZE * slab_no));
 	struct slab_cache *clazz = slab->cache;
 
-	void *brk_start = (void *)CACHEALIGN((void *)slab+sizeof(struct slab));
-	struct slab_item *item = brk_start + item_no * clazz->item_size;
+	void *brk_start = (char *)CACHEALIGN((char *)slab+sizeof(struct slab));
+	struct slab_item *item = (struct slab_item *)((char *) brk_start + item_no * clazz->item_size);
 	assert(valid_item(slab, item));
 
 	return (void *) item;
diff --git a/src/say.m b/src/say.cc
similarity index 95%
rename from src/say.m
rename to src/say.cc
index b0fa1b29860bf5ff4de27657aeddbe7b3dc9ba71..b3e5db473adb32a1e705b2264ebe34fd9b55c6e0 100644
--- a/src/say.m
+++ b/src/say.cc
@@ -39,7 +39,10 @@
 #endif
 
 #include <fiber.h>
-#include TARANTOOL_CONFIG
+extern "C" {
+#include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
 #include "tarantool.h"
 #include "sio.h"
 
@@ -72,7 +75,9 @@ say_logger_init(int nonblock)
 {
 	int pipefd[2];
 	pid_t pid;
-	char *argv[] = { "/bin/sh", "-c", cfg.logger, NULL };
+	char cmd[] = { "/bin/sh" };
+	char args[] = { "-c" };
+	char *argv[] = { cmd, args, cfg.logger, NULL };
 	char *envp[] = { NULL };
 
 	if (cfg.logger != NULL) {
@@ -178,7 +183,7 @@ void
 _say(int level, const char *filename, int line, const char *error, const char *format, ...)
 {
 	int errsv = errno; /* Preserve the errno. */
-        if (cfg.log_level < level)
+	if (cfg.log_level < level)
 		return;
 	va_list ap;
 	va_start(ap, format);
diff --git a/src/scoped_guard.cc b/src/scoped_guard.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f7414593c8eb629fce8602fd4f3f9088030e76f9
--- /dev/null
+++ b/src/scoped_guard.cc
@@ -0,0 +1,30 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "scoped_guard.h"
diff --git a/src/session.m b/src/session.cc
similarity index 89%
rename from src/session.m
rename to src/session.cc
index 034c44d97818e307af1fd22785307a7a5d61a9dd..26f5e3ee1845de8cc5faeb88c67d5d0042024ec9 100644
--- a/src/session.m
+++ b/src/session.cc
@@ -47,14 +47,14 @@ session_create(int fd)
 		;
 
 	uint32_t sid = sid_max;
-	struct mh_i32ptr_node_t node = {
-		.key = sid, .val =  (void *) (intptr_t) fd
-	};
+	struct mh_i32ptr_node_t node;
+	node.key = sid;
+	node.val = (void *) (intptr_t) fd;
 
 	mh_int_t k = mh_i32ptr_put(session_registry, &node, NULL, NULL);
 
 	if (k == mh_end(session_registry)) {
-		tnt_raise(ClientError, :ER_MEMORY_ISSUE,
+		tnt_raise(ClientError, ER_MEMORY_ISSUE,
 			  "session hash", "new session");
 	}
 	/*
@@ -64,12 +64,12 @@ session_create(int fd)
 	fiber_set_sid(fiber, sid);
 	if (session_on_connect.trigger) {
 		void *param = session_on_connect.param;
-		@try {
+		try {
 			session_on_connect.trigger(param);
-		} @catch (tnt_Exception *e) {
+		} catch (const Exception& e) {
 			fiber_set_sid(fiber, 0);
 			mh_i32ptr_remove(session_registry, &node, NULL);
-			@throw;
+			throw;
 		}
 	}
 
@@ -84,22 +84,22 @@ session_destroy(uint32_t sid)
 
 	if (session_on_disconnect.trigger) {
 		void *param = session_on_disconnect.param;
-		@try {
+		try {
 			session_on_disconnect.trigger(param);
-		} @catch (tnt_Exception *e) {
-			[e log];
-		} @catch (id e) {
+		} catch (const Exception& e) {
+			e.log();
+		} catch (...) {
 			/* catch all. */
 		}
 	}
-	struct mh_i32ptr_node_t node = { .key = sid };
+	struct mh_i32ptr_node_t node = { sid, NULL };
 	mh_i32ptr_remove(session_registry, &node, NULL);
 }
 
 int
 session_fd(uint32_t sid)
 {
-	struct mh_i32ptr_node_t node = { .key = sid };
+	struct mh_i32ptr_node_t node = { sid, NULL };
 	mh_int_t k = mh_i32ptr_get(session_registry, &node, NULL);
 	return k == mh_end(session_registry) ?
 		-1 : (intptr_t) mh_i32ptr_node(session_registry, k)->val;
diff --git a/src/sio.m b/src/sio.cc
similarity index 87%
rename from src/sio.m
rename to src/sio.cc
index 4118db8d2e542d3c3ba27d2a0a53b0f0b5ab2c0e..03d592df635c16f85144e547efc7e30e736b8bf7 100644
--- a/src/sio.m
+++ b/src/sio.cc
@@ -37,6 +37,23 @@
 
 #include "say.h"
 
+SocketError::SocketError(const char *file, unsigned line, int fd,
+			 const char *format, ...)
+	: SystemError(file, line)
+{
+	int save_errno = errno;
+
+	char buf[TNT_ERRMSG_MAX];
+
+	va_list ap;
+	va_start(ap, format);
+	vsnprintf(buf, sizeof(buf), format, ap);
+	const char *socketname = sio_socketname(fd);
+	init("%s, called on %s", buf, socketname);
+	va_end(ap);
+	errno = save_errno;
+}
+
 /** Pretty print socket name and peer (for exceptions) */
 const char *
 sio_socketname(int fd)
@@ -61,28 +78,6 @@ sio_socketname(int fd)
 	return name;
 }
 
-@implementation SocketError
-- (id) init: (int) fd in: (const char *) format: (va_list) ap
-{
-	int save_errno = errno;
-	char buf[TNT_ERRMSG_MAX];
-	vsnprintf(buf, sizeof(buf), format, ap);
-	const char *socketname = sio_socketname(fd);
-	errno = save_errno;
-	self = [self init: "%s, called on %s", buf, socketname];
-	return self;
-}
-
-- (id) init: (int) fd in: (const char *) format, ...
-{
-	va_list ap;
-	va_start(ap, format);
-	self = [self init: fd in:format :ap];
-	va_end(ap);
-	return self;
-}
-@end
-
 /** Get a string representation of a socket option name,
  * for logging.
  */
@@ -108,7 +103,7 @@ sio_shutdown(int fd, int how)
 {
 	int rc = shutdown(fd, how);
 	if (rc < 0)
-		tnt_raise(SocketError, :fd in:"shutdown");
+		tnt_raise(SocketError, fd, "shutdown");
 	return rc;
 }
 
@@ -139,7 +134,7 @@ sio_socket(int domain, int type, int protocol)
 {
 	int fd = socket(domain, type, protocol);
 	if (fd < 0)
-		tnt_raise(SocketError, :fd in:"socket");
+		tnt_raise(SocketError, fd, "socket");
 	return fd;
 }
 
@@ -149,7 +144,7 @@ sio_getfl(int fd)
 {
 	int flags = fcntl(fd, F_GETFL, 0);
 	if (flags < 0)
-		tnt_raise(SocketError, :fd in:"fcntl(..., F_GETFL, ...)");
+		tnt_raise(SocketError, fd, "fcntl(..., F_GETFL, ...)");
 	return flags;
 }
 
@@ -160,7 +155,7 @@ sio_setfl(int fd, int flag, int on)
 	int flags = sio_getfl(fd);
 	flags = fcntl(fd, F_SETFL, on ? flags | flag : flags & ~flag);
 	if (flags < 0)
-		tnt_raise(SocketError, :fd in:"fcntl(..., F_SETFL, ...)");
+		tnt_raise(SocketError, fd, "fcntl(..., F_SETFL, ...)");
 	return flags;
 }
 
@@ -171,7 +166,7 @@ sio_setsockopt(int fd, int level, int optname,
 {
 	int rc = setsockopt(fd, level, optname, optval, optlen);
 	if (rc) {
-		tnt_raise(SocketError, :fd in:"setsockopt(%s)",
+		tnt_raise(SocketError, fd, "setsockopt(%s)",
 			  sio_option_name(optname));
 	}
 }
@@ -183,7 +178,7 @@ sio_getsockopt(int fd, int level, int optname,
 {
 	int rc = getsockopt(fd, level, optname, optval, optlen);
 	if (rc) {
-		tnt_raise(SocketError, :fd in:"getsockopt(%s)",
+		tnt_raise(SocketError, fd, "getsockopt(%s)",
 			  sio_option_name(optname));
 	}
 }
@@ -195,7 +190,7 @@ sio_connect(int fd, struct sockaddr_in *addr, socklen_t addrlen)
 	/* Establish the connection. */
 	int rc = connect(fd, (struct sockaddr *) addr, addrlen);
 	if (rc < 0 && errno != EINPROGRESS) {
-		tnt_raise(SocketError, :fd in:"connect");
+		tnt_raise(SocketError, fd, "connect");
 	}
 	return rc;
 }
@@ -206,7 +201,7 @@ sio_bind(int fd, struct sockaddr_in *addr, socklen_t addrlen)
 {
 	int rc = bind(fd, (struct sockaddr *) addr, addrlen);
 	if (rc < 0 && errno != EADDRINUSE)
-		tnt_raise(SocketError, :fd in:"bind");
+		tnt_raise(SocketError, fd, "bind");
 	return rc;
 }
 
@@ -216,7 +211,7 @@ sio_listen(int fd)
 {
 	int rc = listen(fd, sio_listen_backlog());
 	if (rc < 0 && errno != EADDRINUSE)
-		tnt_raise(SocketError, :fd in:"listen");
+		tnt_raise(SocketError, fd, "listen");
 	return rc;
 }
 
@@ -227,7 +222,7 @@ sio_accept(int fd, struct sockaddr_in *addr, socklen_t *addrlen)
 	/* Accept a connection. */
 	int newfd = accept(fd, (struct sockaddr *) addr, addrlen);
 	if (newfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
-		tnt_raise(SocketError, :fd in:"accept");
+		tnt_raise(SocketError, fd, "accept");
 	return newfd;
 }
 
@@ -238,7 +233,7 @@ sio_read(int fd, void *buf, size_t count)
 	ssize_t n = read(fd, buf, count);
 	if (n < 0 && errno != EAGAIN &&
 	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, :fd in:"read(%zd)", count);
+			tnt_raise(SocketError, fd, "read(%zd)", count);
 	return n;
 }
 
@@ -249,7 +244,7 @@ sio_write(int fd, const void *buf, size_t count)
 	ssize_t n = write(fd, buf, count);
 	if (n < 0 && errno != EAGAIN &&
 	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, :fd in:"write(%zd)", count);
+			tnt_raise(SocketError, fd, "write(%zd)", count);
 	return n;
 }
 
@@ -261,7 +256,7 @@ sio_writev(int fd, const struct iovec *iov, int iovcnt)
 	ssize_t n = writev(fd, iov, cnt);
 	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
 	    errno != EINTR) {
-		tnt_raise(SocketError, :fd in:"writev(%d)", iovcnt);
+		tnt_raise(SocketError, fd, "writev(%d)", iovcnt);
 	}
 	return n;
 }
@@ -275,7 +270,7 @@ sio_sendto(int fd, const void *buf, size_t len, int flags,
 	                   addrlen);
 	if (n < 0 && errno != EAGAIN &&
 	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, :fd in:"sendto(%zd)", len);
+			tnt_raise(SocketError, fd, "sendto(%zd)", len);
 	return n;
 }
 
@@ -288,7 +283,7 @@ sio_recvfrom(int fd, void *buf, size_t len, int flags,
 	                     addrlen);
 	if (n < 0 && errno != EAGAIN &&
 	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, :fd in:"recvfrom(%zd)", len);
+			tnt_raise(SocketError, fd, "recvfrom(%zd)", len);
 	return n;
 }
 
diff --git a/src/stat.m b/src/stat.cc
similarity index 97%
rename from src/stat.m
rename to src/stat.cc
index 543e71405c3254a354d90ab8efe83c699fdff5f7..703245f6c5e2783030cb55292ebc528b6ff8e2c6 100644
--- a/src/stat.m
+++ b/src/stat.cc
@@ -38,7 +38,7 @@
 #define SECS 5
 static ev_timer timer;
 
-struct {
+struct stats {
 	const char *name;
 	i64 value[SECS + 1];
 } *stats = NULL;
@@ -66,7 +66,7 @@ stat_register(const char **name, size_t max_idx)
 	for (int i = 0; i < max_idx; i++, name++, base++) {
 		if (stats_size <= base) {
 			stats_size += 1024;
-			stats = realloc(stats, sizeof(*stats) * stats_size);
+			stats = (struct stats *) realloc(stats, sizeof(*stats) * stats_size);
 			if (stats == NULL)
 				abort();
 		}
diff --git a/src/tarantool.m b/src/tarantool.cc
similarity index 83%
rename from src/tarantool.m
rename to src/tarantool.cc
index 10ea0ff2e04e160197a9b5d1d458aa391c6e968e..2fccc14804baceb1257d055b193b3bec4ec36442 100644
--- a/src/tarantool.m
+++ b/src/tarantool.cc
@@ -58,20 +58,21 @@
 #include <say.h>
 #include <stat.h>
 #include <limits.h>
-#include TARANTOOL_CONFIG
 #include <util.h>
-#include <third_party/gopt/gopt.h>
+extern "C" {
 #include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+#include <third_party/gopt/gopt.h>
+} /* extern "C" */
 #include "tarantool_pthread.h"
 #include "lua/init.h"
 #include "memcached.h"
 #include "session.h"
 #include "box/box.h"
+#include "scoped_guard.h"
 
 
 static pid_t master_pid;
-#define DEFAULT_CFG_FILENAME "tarantool.cfg"
-#define DEFAULT_CFG SYSCONF_DIR "/" DEFAULT_CFG_FILENAME
 const char *cfg_filename = NULL;
 char *cfg_filename_fullpath = NULL;
 char *binary_filename;
@@ -84,13 +85,14 @@ static ev_signal *sigs = NULL;
 
 int snapshot_pid = 0; /* snapshot processes pid */
 bool init_storage, booting = true;
+extern const void *opt_def;
 
 static int
 core_check_config(struct tarantool_cfg *conf)
 {
 	if (strindex(wal_mode_STRS, conf->wal_mode,
 		     WAL_MODE_MAX) == WAL_MODE_MAX) {
-		out_warning(0, "wal_mode %s is not recognized", conf->wal_mode);
+		out_warning(CNF_OK, "wal_mode %s is not recognized", conf->wal_mode);
 		return -1;
 	}
 	return 0;
@@ -110,8 +112,8 @@ title(const char *fmt, ...)
 			cfg.memcached_port, cfg.admin_port,
 			cfg.replication_port };
 	int *pptr = ports;
-	char *names[] = { "pri", "sec", "memc", "adm", "rpl", NULL };
-	char **nptr = names;
+	const char *names[] = { "pri", "sec", "memc", "adm", "rpl", NULL };
+	const char **nptr = names;
 
 	for (; *nptr; nptr++, pptr++)
 		if (*pptr)
@@ -135,7 +137,7 @@ load_cfg(struct tarantool_cfg *conf, i32 check_rdonly)
 		f = fopen(cfg_filename, "r");
 
 	if (f == NULL) {
-		out_warning(0, "can't open config `%s'", cfg_filename);
+		out_warning(CNF_OK, "can't open config `%s'", cfg_filename);
 		return -1;
 	}
 
@@ -155,7 +157,7 @@ load_cfg(struct tarantool_cfg *conf, i32 check_rdonly)
 		return -1;
 
 	if (n_accepted == 0) {
-		out_warning(0, "empty configuration file '%s'", cfg_filename);
+		out_warning(CNF_OK, "empty configuration file '%s'", cfg_filename);
 		return -1;
 	}
 
@@ -182,7 +184,7 @@ core_reload_config(const struct tarantool_cfg *old_conf,
 	if (strcasecmp(old_conf->wal_mode, new_conf->wal_mode)) {
 		if (strcasecmp(old_conf->wal_mode, "fsync") == 0 ||
 		    strcasecmp(new_conf->wal_mode, "fsync") == 0) {
-			out_warning(0, "wal_mode cannot switch to/from fsync");
+			out_warning(CNF_OK, "wal_mode cannot switch to/from fsync");
 			return -1;
 		}
 		say_debug("%s: wal_mode [%s] -> [%s]",
@@ -215,61 +217,19 @@ reload_cfg(struct tbuf *out)
 	struct tarantool_cfg new_cfg, aux_cfg;
 
 	if (mutex == NULL) {
-		mutex = palloc(eter_pool, sizeof(*mutex));
+		mutex = (struct mutex *) palloc(eter_pool, sizeof(*mutex));
 		mutex_create(mutex);
 	}
 
 	if (mutex_trylock(mutex) == true) {
-		out_warning(0, "Could not reload configuration: it is being reloaded right now");
+		out_warning(CNF_OK, "Could not reload configuration: it is being reloaded right now");
 		tbuf_append(out, cfg_out->data, cfg_out->size);
 
 		return -1;
 	}
 
-	@try {
-		init_tarantool_cfg(&new_cfg);
-		init_tarantool_cfg(&aux_cfg);
-
-		/*
-		  Prepare a copy of the original config file
-		  for confetti, so that it can compare the new
-		  file with the old one when loading the new file.
-		  Load the new file and return an error if it
-		  contains a different value for some read-only
-		  parameter.
-		*/
-		if (dup_tarantool_cfg(&aux_cfg, &cfg) != 0 ||
-		    load_cfg(&aux_cfg, 1) != 0)
-			return -1;
-		/*
-		  Load the new configuration file, but
-		  skip the check for read only parameters.
-		  new_cfg contains only defaults and
-		  new settings.
-		*/
-		if (fill_default_tarantool_cfg(&new_cfg) != 0 ||
-		    load_cfg(&new_cfg, 0) != 0)
-			return -1;
-
-		/* Check that no default value has been changed. */
-		char *diff = cmp_tarantool_cfg(&aux_cfg, &new_cfg, 1);
-		if (diff != NULL) {
-			out_warning(0, "Could not accept read only '%s' option", diff);
-			return -1;
-		}
-
-		/* Process wal-writer-related changes. */
-		if (core_reload_config(&cfg, &new_cfg) != 0)
-			return -1;
 
-		/* Now pass the config to the module, to take action. */
-		if (box_reload_config(&cfg, &new_cfg) != 0)
-			return -1;
-		/* All OK, activate the config. */
-		swap_tarantool_cfg(&cfg, &new_cfg);
-		tarantool_lua_load_cfg(tarantool_L, &cfg);
-	}
-	@finally {
+	auto scoped_guard = make_scoped_guard([&] {
 		destroy_tarantool_cfg(&aux_cfg);
 		destroy_tarantool_cfg(&new_cfg);
 
@@ -277,7 +237,50 @@ reload_cfg(struct tbuf *out)
 			tbuf_append(out, cfg_out->data, cfg_out->size);
 
 		mutex_unlock(mutex);
+	});
+
+	init_tarantool_cfg(&new_cfg);
+	init_tarantool_cfg(&aux_cfg);
+
+	/*
+	  Prepare a copy of the original config file
+	   for confetti, so that it can compare the new
+	  file with the old one when loading the new file.
+	  Load the new file and return an error if it
+	  contains a different value for some read-only
+	  parameter.
+	*/
+	if (dup_tarantool_cfg(&aux_cfg, &cfg) != 0 ||
+	    load_cfg(&aux_cfg, 1) != 0)
+		return -1;
+	/*
+	  Load the new configuration file, but
+	  skip the check for read only parameters.
+	  new_cfg contains only defaults and
+	  new settings.
+	*/
+	if (fill_default_tarantool_cfg(&new_cfg) != 0 ||
+	    load_cfg(&new_cfg, 0) != 0)
+		return -1;
+
+	/* Check that no default value has been changed. */
+	char *diff = cmp_tarantool_cfg(&aux_cfg, &new_cfg, 1);
+	if (diff != NULL) {
+		out_warning(CNF_OK, "Could not accept read only '%s' option", diff);
+		return -1;
 	}
+
+	/* Process wal-writer-related changes. */
+	if (core_reload_config(&cfg, &new_cfg) != 0)
+		return -1;
+
+	/* Now pass the config to the module, to take action. */
+	if (box_reload_config(&cfg, &new_cfg) != 0)
+		return -1;
+	/* All OK, activate the config. */
+	swap_tarantool_cfg(&cfg, &new_cfg);
+	tarantool_lua_load_cfg(tarantool_L, &cfg);
+
 	return 0;
 }
 
@@ -351,8 +354,11 @@ snapshot(void)
 * Create snapshot from signal handler (SIGUSR1)
 */
 static void
-sig_snapshot(void)
+sig_snapshot(struct ev_signal *w, int revents)
 {
+	(void) w;
+	(void) revents;
+
 	if (snapshot_pid) {
 		say_warn("Snapshot process is already running,"
 			" the signal is ignored");
@@ -362,8 +368,11 @@ sig_snapshot(void)
 }
 
 static void
-signal_cb(void)
+signal_cb(struct ev_signal *w, int revents)
 {
+	(void) w;
+	(void) revents;
+
 	/* Terminate the main event loop */
 	ev_unloop(EV_A_ EVUNLOOP_ALL);
 }
@@ -485,15 +494,15 @@ signal_init(void)
 		exit(EX_OSERR);
 	}
 
-	sigs = palloc(eter_pool, sizeof(ev_signal) * 4);
+	sigs = (ev_signal *) palloc(eter_pool, sizeof(ev_signal) * 4);
 	memset(sigs, 0, sizeof(ev_signal) * 4);
-	ev_signal_init(&sigs[0], (void*)sig_snapshot, SIGUSR1);
+	ev_signal_init(&sigs[0], sig_snapshot, SIGUSR1);
 	ev_signal_start(&sigs[0]);
-	ev_signal_init(&sigs[1], (void*)signal_cb, SIGINT);
+	ev_signal_init(&sigs[1], signal_cb, SIGINT);
 	ev_signal_start(&sigs[1]);
-	ev_signal_init(&sigs[2], (void*)signal_cb, SIGTERM);
+	ev_signal_init(&sigs[2], signal_cb, SIGTERM);
 	ev_signal_start(&sigs[2]);
-	ev_signal_init(&sigs[3], (void*)signal_cb, SIGHUP);
+	ev_signal_init(&sigs[3], signal_cb, SIGHUP);
 	ev_signal_start(&sigs[3]);
 
 	atexit(signal_free);
@@ -641,29 +650,6 @@ main(int argc, char **argv)
 	main_argc = argc;
 	main_argv = argv;
 
-	const void *opt_def =
-		gopt_start(gopt_option('g', GOPT_ARG, gopt_shorts(0),
-				       gopt_longs("cfg-get", "cfg_get"),
-				       "=KEY", "return a value from configuration file described by KEY"),
-			   gopt_option('k', 0, gopt_shorts(0),
-				       gopt_longs("check-config"),
-				       NULL, "Check configuration file for errors"),
-			   gopt_option('c', GOPT_ARG, gopt_shorts('c'),
-				       gopt_longs("config"),
-				       "=FILE", "path to configuration file (default: " DEFAULT_CFG_FILENAME ")"),
-			   gopt_option('I', 0, gopt_shorts(0),
-				       gopt_longs("init-storage", "init_storage"),
-				       NULL, "initialize storage (an empty snapshot file) and exit"),
-			   gopt_option('v', 0, gopt_shorts('v'), gopt_longs("verbose"),
-				       NULL, "increase verbosity level in log messages"),
-			   gopt_option('B', 0, gopt_shorts('B'), gopt_longs("background"),
-				       NULL, "redirect input/output streams to a log file and run as daemon"),
-			   gopt_option('h', 0, gopt_shorts('h', '?'), gopt_longs("help"),
-				       NULL, "display this help and exit"),
-			   gopt_option('V', 0, gopt_shorts('V'), gopt_longs("version"),
-				       NULL, "print program version and exit")
-		);
-
 	void *opt = gopt_sort(&argc, (const char **)argv, opt_def);
 	main_opt = opt;
 	binary_filename = argv[0];
@@ -674,6 +660,7 @@ main(int argc, char **argv)
 		printf("Build options: %s\n", BUILD_OPTIONS);
 		printf("Compiler: %s\n", COMPILER_INFO);
 		printf("C_FLAGS:%s\n", TARANTOOL_C_FLAGS);
+		printf("CXX_FLAGS:%s\n", TARANTOOL_CXX_FLAGS);
 		return 0;
 	}
 
@@ -710,7 +697,7 @@ main(int argc, char **argv)
 	}
 
 	if (cfg_filename[0] != '/') {
-		cfg_filename_fullpath = malloc(PATH_MAX);
+		cfg_filename_fullpath = (char *) malloc(PATH_MAX);
 		if (getcwd(cfg_filename_fullpath, PATH_MAX - strlen(cfg_filename) - 1) == NULL) {
 			say_syserror("getcwd");
 			exit(EX_OSERR);
@@ -826,9 +813,10 @@ main(int argc, char **argv)
 
 	/* init process title */
 	if (cfg.custom_proc_title == NULL) {
-		custom_proc_title = "";
+		custom_proc_title = (char *) palloc(eter_pool, 1);
+		custom_proc_title[0] = '\0';
 	} else {
-		custom_proc_title = palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
+		custom_proc_title = (char *) palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
 		strcpy(custom_proc_title, "@");
 		strcat(custom_proc_title, cfg.custom_proc_title);
 	}
@@ -848,7 +836,7 @@ main(int argc, char **argv)
 	signal_init();
 
 
-	@try {
+	try {
 		tarantool_L = tarantool_lua_init();
 		box_init();
 		memcached_init(cfg.bind_ipaddr, cfg.memcached_port);
@@ -882,10 +870,11 @@ main(int argc, char **argv)
 		ev_now_update();
 		start_time = ev_now();
 		ev_loop(0);
-	} @catch (tnt_Exception *e) {
-		[e log];
+	} catch (const Exception& e) {
+		e.log();
 		panic("%s", "Fatal error, exiting loop");
 	}
+
 	say_crit("exiting loop");
 	/* freeing resources */
 	return 0;
diff --git a/src/tbuf.m b/src/tbuf.c
similarity index 91%
rename from src/tbuf.m
rename to src/tbuf.c
index cc8612577f2c4fb061b44aa61cbab35d8381496f..28f6a65dbad030c94a787d0651ae9c0f9860bd41 100644
--- a/src/tbuf.m
+++ b/src/tbuf.c
@@ -60,7 +60,7 @@ tbuf_assert(const struct tbuf *b)
 struct tbuf *
 tbuf_new(struct palloc_pool *pool)
 {
-	struct tbuf *e = palloc(pool, TBUF_ALLOC_FACTOR);
+	struct tbuf *e = (struct tbuf *) palloc(pool, TBUF_ALLOC_FACTOR);
 	e->size = 0;
 	e->capacity = TBUF_ALLOC_FACTOR - sizeof(struct tbuf);
 	e->data = (char *)e + sizeof(struct tbuf);
@@ -76,7 +76,7 @@ tbuf_ensure_resize(struct tbuf *e, size_t required)
 	tbuf_assert(e);
 
 	/* Make new capacity a multiple of alloc factor. */
-	size_t new_capacity = MAX(e->capacity, TBUF_ALLOC_FACTOR) * 2;
+	size_t new_capacity = MAX(e->capacity, (uint32_t)TBUF_ALLOC_FACTOR) * 2;
 
 	while (new_capacity < e->size + required)
 		new_capacity *= 2;
@@ -86,7 +86,7 @@ tbuf_ensure_resize(struct tbuf *e, size_t required)
 	poison(p, new_capacity);
 	memcpy(p, e->data, e->size);
 	poison(e->data, e->size);
-	e->data = p;
+	e->data = (char *) p;
 	e->capacity = new_capacity;
 	tbuf_assert(e);
 }
@@ -103,13 +103,13 @@ tbuf_clone(struct palloc_pool *pool, const struct tbuf *orig)
 struct tbuf *
 tbuf_split(struct tbuf *orig, size_t at)
 {
-	struct tbuf *head = palloc(orig->pool, sizeof(*orig));
+	struct tbuf *head = (struct tbuf *) palloc(orig->pool, sizeof(*orig));
 	assert(at <= orig->size);
 	tbuf_assert(orig);
 	head->pool = orig->pool;
 	head->data = orig->data;
 	head->size = head->capacity = at;
-	orig->data += at;
+	orig->data = (char *) orig->data + at;
 	orig->capacity -= at;
 	orig->size -= at;
 	return head;
@@ -121,7 +121,7 @@ tbuf_peek(struct tbuf *b, size_t count)
 	void *p = b->data;
 	tbuf_assert(b);
 	if (count <= b->size) {
-		b->data += count;
+		b->data = (char *) b->data + count;
 		b->size -= count;
 		b->capacity -= count;
 		return p;
@@ -190,9 +190,9 @@ tbuf_printf(struct tbuf *b, const char *format, ...)
 char *
 tbuf_to_hex(const struct tbuf *x)
 {
-	const unsigned char *data = x->data;
+	const char *data = x->data;
 	size_t size = x->size;
-	char *out = palloc(x->pool, size * 3 + 1);
+	char *out = (char *) palloc(x->pool, size * 3 + 1);
 	out[size * 3] = 0;
 
 	for (int i = 0; i < size; i++) {
diff --git a/src/trace.m b/src/trace.c
similarity index 100%
rename from src/trace.m
rename to src/trace.c
diff --git a/src/util.m b/src/util.c
similarity index 92%
rename from src/util.m
rename to src/util.c
index 799d62f5efa187f7aed7f6640e5d7519e4bbcf2f..2e5c5c70761d8dda39e56641b487e3613a9bf1cb 100644
--- a/src/util.m
+++ b/src/util.c
@@ -42,7 +42,7 @@
 #include <bfd.h>
 #endif /* HAVE_BFD */
 
-#include <fiber.h>
+#include "fiber.h"
 #include "say.h"
 
 #ifndef HAVE_LIBC_STACK_END
@@ -223,15 +223,15 @@ struct frame {
 char *
 backtrace(void *frame_, void *stack, size_t stack_size)
 {
-	struct frame *frame = frame_;
-	void *stack_top = stack + stack_size;
+	struct frame *frame = (struct frame *) frame_;
+	void *stack_top = (char *) stack + stack_size;
 	void *stack_bottom = stack;
 
 	char *p = backtrace_buf;
 	size_t r, len = sizeof(backtrace_buf);
 	while (stack_bottom <= (void *)frame && (void *)frame < stack_top) {
 		r = snprintf(p, len, "        - { frame: %p, caller: %p",
-			     (void *)frame + 2 * sizeof(void *), frame->ret);
+			     (char *)frame + 2 * sizeof(void *), frame->ret);
 
 		if (r >= len)
 			goto out;
@@ -241,7 +241,7 @@ backtrace(void *frame_, void *stack, size_t stack_size)
 #ifdef HAVE_BFD
 		struct symbol *s = addr2symbol(frame->ret);
 		if (s != NULL) {
-			r = snprintf(p, len, " <%s+%"PRI_SZ"> ", s->name, frame->ret - s->addr);
+			r = snprintf(p, len, " <%s+%" PRI_SZ "> ", s->name, (const char *) frame->ret - (const char *) s->addr);
 			if (r >= len)
 				goto out;
 			p += r;
@@ -266,7 +266,7 @@ backtrace(void *frame_, void *stack, size_t stack_size)
 out:
 	p += MIN(len - 1, r);
 	*p = 0;
-        return backtrace_buf;
+	return backtrace_buf;
 }
 
 void
@@ -279,7 +279,7 @@ print_backtrace()
 	if (fiber == NULL || fiber_name(fiber) == NULL ||
 	    strcmp(fiber_name(fiber), "sched") == 0) {
 		stack_top = frame; /* we don't know where the system stack top is */
-		stack_size = __libc_stack_end - frame;
+		stack_size = (const char *) __libc_stack_end - (const char *) frame;
 	} else {
 		stack_top = fiber->coro.stack;
 		stack_size = fiber->coro.stack_size;
@@ -308,7 +308,8 @@ static ssize_t symbol_count;
 int
 compare_symbol(const void *_a, const void *_b)
 {
-	const struct symbol *a = _a, *b = _b;
+	const struct symbol *a = (const struct symbol *) _a;
+	const struct symbol *b = (const struct symbol *) _b;
 	if (a->addr > b->addr)
 		return 1;
 	if (a->addr == b->addr)
@@ -340,9 +341,9 @@ symbols_load(const char *name)
 	storage_needed = bfd_get_symtab_upper_bound(h);
 
 	if (storage_needed <= 0)
-                goto out;
+		goto out;
 
-	symbol_table = malloc(storage_needed);
+	symbol_table = (asymbol **) malloc(storage_needed);
 	if (symbol_table == NULL)
 		goto out;
 
@@ -370,7 +371,7 @@ symbols_load(const char *name)
 		goto out;
 
 	j = 0;
-	symbols = malloc(symbol_count * sizeof(struct symbol));
+	symbols = (struct symbol *) malloc(symbol_count * sizeof(struct symbol));
 	if (symbols == NULL)
 		goto out;
 
@@ -399,7 +400,8 @@ symbols_load(const char *name)
 	qsort(symbols, symbol_count, sizeof(struct symbol), compare_symbol);
 
 	for (int j = 0; j < symbol_count - 1; j++)
-		symbols[j].end = MIN(symbols[j].end, symbols[j + 1].addr - 1);
+		symbols[j].end = MIN((char *) symbols[j].end,
+				     (char *) symbols[j + 1].addr - 1);
 
 out:
 	if (symbol_count == 0)
diff --git a/test/box/args.result b/test/box/args.result
index 8905849a1dfabc4661725cbb544d2b033f553850..5d0b6846eaa21369c784c43f4881f1347a2f0ce3 100644
--- a/test/box/args.result
+++ b/test/box/args.result
@@ -75,6 +75,7 @@ Target: platform <build>
 Build options: flags
 Compiler: cc
 C_FLAGS: flags
+CXX_FLAGS: flags
 
 tarantool_box -V
 Tarantool 1.minor.patch-<rev>-<commit>
@@ -82,6 +83,7 @@ Target: platform <build>
 Build options: flags
 Compiler: cc
 C_FLAGS: flags
+CXX_FLAGS: flags
 
 #
 # A test case for Bug#726778 "Gopt broke wal_dir and snap_dir: they are no
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 982a932569cd0c8fb395dc2bd97d74c336c9b395..20f2d55fc55d30f51f208b6f43ba785c4744ebd2 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -16,16 +16,3 @@ add_executable(bitset_iterator_test bitset_iterator.c)
 target_link_libraries(bitset_iterator_test bitset)
 add_executable(bitset_index_test bitset_index.c)
 target_link_libraries(bitset_index_test bitset)
-
-add_executable(objc_finally objc_finally.m)
-include_directories(${LIBOBJC_INCLUDE_DIR})
-add_executable(objc_catchcxx objc_catchcxx.m)
-
-add_dependencies(objc_finally build_bundled_libs)
-add_dependencies(objc_catchcxx build_bundled_libs)
-
-target_link_libraries(objc_finally ${LIBOBJC_LIBRARIES} -lm -pthread)
-target_link_libraries(objc_catchcxx ${LIBOBJC_LIBRARIES} ${LUAJIT_LIB} -lm -pthread)
-if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD)
-    target_link_libraries(objc_catchcxx dl)
-endif()
diff --git a/test/unit/objc_catchcxx.m b/test/unit/objc_catchcxx.m
deleted file mode 100644
index 23fed813b15e27820b2c67d961da6e595a9e8160..0000000000000000000000000000000000000000
--- a/test/unit/objc_catchcxx.m
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-
-int main()
-{
-	lua_State *L = luaL_newstate();
-	luaL_openlibs(L);
-	@try {
-		luaL_error(L, "test");
-	} @catch (id allOthers) {
-		printf("exception handled\n");
-	}
-	lua_close(L);
-
-	return 0;
-}
diff --git a/test/unit/objc_catchcxx.result b/test/unit/objc_catchcxx.result
deleted file mode 100644
index 761f3a20404e3a9aed380cfe9f631e6d231671f8..0000000000000000000000000000000000000000
--- a/test/unit/objc_catchcxx.result
+++ /dev/null
@@ -1 +0,0 @@
-exception handled
diff --git a/test/unit/objc_catchcxx.test b/test/unit/objc_catchcxx.test
deleted file mode 100644
index 13f381fcb7bcb15f5df824b7022269be6f46bbc1..0000000000000000000000000000000000000000
--- a/test/unit/objc_catchcxx.test
+++ /dev/null
@@ -1 +0,0 @@
-run_test("objc_catchcxx")
diff --git a/test/unit/objc_finally.m b/test/unit/objc_finally.m
deleted file mode 100644
index 18cf5c62b5838415226380e92e968d313023f6af..0000000000000000000000000000000000000000
--- a/test/unit/objc_finally.m
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <stdio.h>
-#include <objc/Object.h>
-#include <objc/runtime.h>
-
-@interface Exception: Object {
-}
-+ (id) new;
-@end
-
-@implementation Exception
-+ (id) new
-{
-	return class_createInstance(self, 0);
-}
-@end
-
-void
-throw_exception(void)
-{
-	printf("throw\n");
-	@throw [Exception new];
-}
-
-void
-test(void)
-{
-	@try {
-		throw_exception();
-	} @finally {
-		printf("internal finally\n");
-	}
-}
-
-int
-main(int ac, char **av)
-{
-	printf("start\n");
-	@try {
-		test();
-	} @catch(id e) {
-		printf("catch\n");
-	} @finally {
-		printf("external finally\n");
-	}
-	return 0;
-}
diff --git a/test/unit/objc_finally.result b/test/unit/objc_finally.result
deleted file mode 100644
index 1d09f8b41372dfdb1c732e6c522080975571ae31..0000000000000000000000000000000000000000
--- a/test/unit/objc_finally.result
+++ /dev/null
@@ -1,5 +0,0 @@
-start
-throw
-internal finally
-catch
-external finally
diff --git a/test/unit/objc_finally.test b/test/unit/objc_finally.test
deleted file mode 100644
index 65770394cce04b504544ad9578f2c2203990773c..0000000000000000000000000000000000000000
--- a/test/unit/objc_finally.test
+++ /dev/null
@@ -1 +0,0 @@
-run_test("objc_finally")
diff --git a/third_party/qsort_arg.h b/third_party/qsort_arg.h
index 8a94e1e3b4889257d845d365cd5b9677581e268a..6b9fe44cc012223a8ebeac0dc8c1e8fe8e98ef56 100644
--- a/third_party/qsort_arg.h
+++ b/third_party/qsort_arg.h
@@ -3,6 +3,14 @@
 
 #include <sys/types.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 void qsort_arg(void *a, size_t n, size_t es, int (*cmp)(const void *a, const void *b, void *arg), void *arg);
 
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */
+
 #endif
diff --git a/third_party/sptree.h b/third_party/sptree.h
index b3d74e78e933efdad95f9edbd115be2b65e2108a..e310710c5391ddce59610047f5bc2a80e3780c32 100644
--- a/third_party/sptree.h
+++ b/third_party/sptree.h
@@ -34,6 +34,10 @@
 
 #include <third_party/qsort_arg.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
 #ifndef SPTREE_NODE_SELF
 /*
  * user could suggest pointer's storage himself
@@ -46,8 +50,8 @@ typedef struct sptree_node_pointers {
     u_int32_t    right;
 } sptree_node_pointers;
 
-#define GET_SPNODE_LEFT(snp)        ( (snp)->left ) 
-#define SET_SPNODE_LEFT(snp, v)     (snp)->left = (v) 
+#define GET_SPNODE_LEFT(snp)        ( (snp)->left )
+#define SET_SPNODE_LEFT(snp, v)     (snp)->left = (v)
 #define GET_SPNODE_RIGHT(snp)       ( (snp)->right )
 #define SET_SPNODE_RIGHT(snp, v)    (snp)->right = (v)
 
@@ -63,7 +67,7 @@ typedef struct sptree_node_pointers {
 #define    _GET_SPNODE_RIGHT(n)        GET_SPNODE_RIGHT( t->lrpointers + (n) )
 #define    _SET_SPNODE_RIGHT(n, v)     SET_SPNODE_RIGHT( t->lrpointers + (n), (v) )
 
-#define    ITHELEM(t, i)               ( (t)->members + (t)->elemsize * (i) )
+#define    ITHELEM(t, i)               ( (char *) (t)->members + (t)->elemsize * (i) )
 #define    ELEMIDX(t, e)               ( ((e) - (t)->members) / (t)->elemsize )
 
 /*
@@ -71,8 +75,8 @@ typedef struct sptree_node_pointers {
  * be unique across all definitions.
  *
  * Methods:
- *   void sptree_NAME_init(sptree_NAME *tree, size_t elemsize, void *array, 
- *                         spnode_t array_len, spnode_t array_size, 
+ *   void sptree_NAME_init(sptree_NAME *tree, size_t elemsize, void *array,
+ *                         spnode_t array_len, spnode_t array_size,
  *                         int (*compare)(const void *key, const void *elem, void *arg),
  *                         int (*elemcompare)(const void *e1, const void *e2, void *arg),
  *                         void *arg)
@@ -84,9 +88,9 @@ typedef struct sptree_node_pointers {
  *   spnode_t sptree_NAME_walk(sptree_NAME *t, void* array, spnode_t limit, spnode_t offset)
  *   void sptree_NAME_walk_cb(sptree_NAME *t, int (*cb)(void* cb_arg, void* elem), void *cb_arg)
  *
- *   sptree_NAME_iterator* sptree_NAME_iterator_init(sptree_NAME *t) 
+ *   sptree_NAME_iterator* sptree_NAME_iterator_init(sptree_NAME *t)
  *   void sptree_NAME_iterator_init_set(sptree_NAME *t, sptree_NAME_iterator **iterator, void *start)
- *   sptree_NAME_iterator* sptree_NAME_iterator_reverse_init(sptree_NAME *t) 
+ *   sptree_NAME_iterator* sptree_NAME_iterator_reverse_init(sptree_NAME *t)
  *   void sptree_NAME_iterator_reverse_init_set(sptree_NAME *t, sptree_NAME_iterator **iterator, void *start)
  *   void sptree_NAME_iterator_free(sptree_NAME_iterator *i)
  *
@@ -159,7 +163,8 @@ sptree_##name##_init(sptree_##name *t, size_t elemsize, void *m,
         if (t->members == NULL)                                                           \
             t->members = realloc(NULL, elemsize * t->ntotal);                             \
     }                                                                                     \
-    t->lrpointers = realloc(NULL, sizeof(sptree_node_pointers) * t->ntotal);              \
+    t->lrpointers = (sptree_node_pointers *) realloc(NULL,                                \
+                                sizeof(sptree_node_pointers) * t->ntotal);                \
                                                                                           \
     if (t->nmember == 1) {                                                                \
         t->root = 0;                                                                      \
@@ -181,16 +186,16 @@ sptree_##name##_destroy(sptree_##name *t) {
                                                                                           \
 /** Nodes in the garbage list have a loop on their right link. */                         \
 static inline bool                                                                        \
-sptree_##name##_node_is_deleted(sptree_##name *t, spnode_t node) {                        \
+sptree_##name##_node_is_deleted(const sptree_##name *t, spnode_t node) {                  \
                                                                                           \
     return _GET_SPNODE_RIGHT(node) == node;                                               \
 }                                                                                         \
                                                                                           \
 static inline void*                                                                       \
-sptree_##name##_find(sptree_##name *t, void *k) {                                         \
+sptree_##name##_find(const sptree_##name *t, void *k) {                                   \
     spnode_t    node = t->root;                                                           \
     while(node != SPNIL) {                                                                \
-        int r = t->compare(k, ITHELEM(t, node), t->arg);                                  \
+    int r = t->compare(k, ITHELEM(t, node), t->arg);                                  \
         if (r > 0) {                                                                      \
             node = _GET_SPNODE_RIGHT(node);                                               \
         } else if (r < 0) {                                                               \
@@ -203,7 +208,7 @@ sptree_##name##_find(sptree_##name *t, void *k) {
 }                                                                                         \
                                                                                           \
 static inline void*                                                                       \
-sptree_##name##_first(sptree_##name *t) {                                                 \
+sptree_##name##_first(const sptree_##name *t) {                                           \
     spnode_t    node = t->root;                                                           \
     spnode_t    first = SPNIL;                                                            \
     while (node != SPNIL) {                                                               \
@@ -216,7 +221,7 @@ sptree_##name##_first(sptree_##name *t) {
 }                                                                                         \
                                                                                           \
 static inline void*                                                                       \
-sptree_##name##_last(sptree_##name *t) {                                                  \
+sptree_##name##_last(const sptree_##name *t) {                                            \
     spnode_t    node = t->root;                                                           \
     spnode_t    last = SPNIL;                                                             \
     while (node != SPNIL) {                                                               \
@@ -229,7 +234,7 @@ sptree_##name##_last(sptree_##name *t) {
 }                                                                                         \
                                                                                           \
 static inline void*                                                                       \
-sptree_##name##_random(sptree_##name *t, spnode_t rnd) {                                  \
+sptree_##name##_random(const sptree_##name *t, spnode_t rnd) {                            \
     for (spnode_t i = 0; i < t->size; i++, rnd++) {                                       \
         rnd %= t->nmember;                                                                \
         if (!sptree_##name##_node_is_deleted(t, rnd))                                     \
@@ -258,7 +263,7 @@ sptree_##name##_get_place(sptree_##name *t) {
         if (t->nmember >= t->ntotal) {                                                    \
             t->ntotal *= 2;                                                               \
             t->members = realloc(t->members, t->ntotal * t->elemsize);                    \
-            t->lrpointers = realloc(t->lrpointers,                                        \
+            t->lrpointers = (sptree_node_pointers *) realloc(t->lrpointers,               \
                                     t->ntotal * sizeof(sptree_node_pointers));            \
         }                                                                                 \
                                                                                           \
@@ -498,7 +503,7 @@ sptree_##name##_walk(sptree_##name *t, void* array, spnode_t limit, spnode_t off
     while( count < offset + limit && level >= 0 ) {                                       \
                                                                                           \
         if (count >= offset)                                                              \
-             memcpy(array + (count-offset) * t->elemsize,                                 \
+             memcpy((char *) array + (count-offset) * t->elemsize,                        \
                     ITHELEM(t, stack[level]), t->elemsize);                               \
         count++;                                                                          \
                                                                                           \
@@ -543,7 +548,7 @@ sptree_##name##_walk_cb(sptree_##name *t, int (*cb)(void*, void*), void *cb_arg
 }                                                                                         \
                                                                                           \
 typedef struct sptree_##name##_iterator {                                                 \
-    sptree_##name        *t;                                                              \
+    const sptree_##name        *t;                                                        \
     int                  level;                                                           \
     int                  max_depth;                                                       \
     spnode_t             stack[0];                                                        \
@@ -551,7 +556,7 @@ typedef struct sptree_##name##_iterator {
                                                                                           \
 static inline sptree_##name##_iterator *                                                  \
 sptree_##name##_iterator_alloc(sptree_##name *t) {                                        \
-    sptree_##name##_iterator *i =                                                         \
+    sptree_##name##_iterator *i = (sptree_##name##_iterator *)                            \
         realloc(NULL, sizeof(*i) + sizeof(spnode_t) * (t->max_depth + 1));                \
     i->t = t;                                                                             \
     i->level = 0;                                                                         \
@@ -576,13 +581,14 @@ sptree_##name##_iterator_init(sptree_##name *t) {
 }                                                                                         \
                                                                                           \
 static inline void                                                                        \
-sptree_##name##_iterator_init_set(sptree_##name *t, sptree_##name##_iterator **i,         \
+sptree_##name##_iterator_init_set(const sptree_##name *t, sptree_##name##_iterator **i,   \
                                   void *k) {                                              \
     spnode_t node;                                                                        \
     int      lastLevelEq = -1, cmp;                                                       \
                                                                                           \
     if ((*i) == NULL || t->max_depth > (*i)->max_depth)                                   \
-        *i = realloc(*i, sizeof(**i) + sizeof(spnode_t) * (t->max_depth + 31));            \
+        *i = (sptree_##name##_iterator *) realloc(*i, sizeof(**i) +                       \
+                                       sizeof(spnode_t) * (t->max_depth + 31));           \
                                                                                           \
     (*i)->t = t;                                                                          \
     (*i)->level = -1;                                                                     \
@@ -633,13 +639,14 @@ sptree_##name##_iterator_reverse_init(sptree_##name *t) {
 }                                                                                         \
                                                                                           \
 static inline void                                                                        \
-sptree_##name##_iterator_reverse_init_set(sptree_##name *t, sptree_##name##_iterator **i, \
-                                          void *k) {                                      \
+sptree_##name##_iterator_reverse_init_set(const sptree_##name *t,                         \
+                                          sptree_##name##_iterator **i, void *k) {        \
     spnode_t node;                                                                        \
     int      lastLevelEq = -1, cmp;                                                       \
                                                                                           \
     if ((*i) == NULL || t->max_depth > (*i)->max_depth)                                   \
-        *i = realloc(*i, sizeof(**i) + sizeof(spnode_t) * (t->max_depth + 31));            \
+        *i = (sptree_##name##_iterator *) realloc(*i, sizeof(**i) +                       \
+                                      sizeof(spnode_t) * (t->max_depth + 31));            \
                                                                                           \
     (*i)->t = t;                                                                          \
     (*i)->level = -1;                                                                     \
@@ -699,7 +706,7 @@ sptree_##name##_iterator_next(sptree_##name##_iterator *i) {
                                                                                           \
     if (i == NULL)  return NULL;                                                          \
                                                                                           \
-    sptree_##name *t = i->t;                                                              \
+    const sptree_##name *t = i->t;                                                        \
     spnode_t returnNode = sptree_##name##_iterator_next_node(i);                          \
                                                                                           \
     if (returnNode == SPNIL) return NULL;                                                 \
@@ -719,7 +726,7 @@ sptree_##name##_iterator_reverse_next(sptree_##name##_iterator *i) {
                                                                                           \
     if (i == NULL)  return NULL;                                                          \
                                                                                           \
-    sptree_##name *t = i->t;                                                              \
+    const sptree_##name *t = i->t;                                                        \
     spnode_t returnNode = sptree_##name##_iterator_next_node(i);                          \
                                                                                           \
     if (returnNode == SPNIL) return NULL;                                                 \
@@ -736,3 +743,7 @@ sptree_##name##_iterator_reverse_next(sptree_##name##_iterator *i) {
  * vim: ts=4 sts=4 et
  */
 #endif
+
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */