build: update default CXXFLAGS.

* Add -std=c++03 and -pedantic, and fix the resulting warnings. The
  long-long-int warning is explicitly suppressed because it's not
  trivial to workaround in a platform-independent and ISO-conformant
  way without using C++11.

* Initial support for building with -std=c++11 (experimental).

* Prefer -Og optimization level in debug builds if supported by the
  compiler.

Change-Id: I744a25c8b52842dc3ea3a733d6ab2fa66171e6f8
diff --git a/.waf-tools/boost.py b/.waf-tools/boost.py
index e54f513..305945a 100644
--- a/.waf-tools/boost.py
+++ b/.waf-tools/boost.py
@@ -61,6 +61,14 @@
 #include <boost/version.hpp>
 int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
 '''
+BOOST_SYSTEM_CODE = '''
+#include <boost/system/error_code.hpp>
+int main() { boost::system::error_code c; }
+'''
+BOOST_THREAD_CODE = '''
+#include <boost/thread.hpp>
+int main() { boost::thread t; }
+'''
 
 # toolsets from {boost_dir}/tools/build/v2/tools/common.jam
 PLATFORM = Utils.unversioned_sys_platform()
@@ -96,10 +104,10 @@
 
 	opt.add_option('--boost-includes', type='string',
 				   default='', dest='boost_includes',
-				   help='''path to the directory where the boost includes are, e.g., /path/to/boost_1_47_0/stage/include''')
+				   help='''path to the directory where the boost includes are, e.g., /path/to/boost_1_55_0/stage/include''')
 	opt.add_option('--boost-libs', type='string',
 				   default='', dest='boost_libs',
-				   help='''path to the directory where the boost libs are, e.g., /path/to/boost_1_47_0/stage/lib''')
+				   help='''path to the directory where the boost libs are, e.g., /path/to/boost_1_55_0/stage/lib''')
 	opt.add_option('--boost-static', action='store_true',
 				   default=False, dest='boost_static',
 				   help='link with static boost libraries (.lib/.a)')
@@ -136,10 +144,10 @@
 		except (OSError, IOError):
 			Logs.error("Could not read the file %r" % node.abspath())
 		else:
-			re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"', re.M)
+			re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
 			m1 = re_but1.search(txt)
 
-			re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+"(.*)"', re.M)
+			re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
 			m2 = re_but2.search(txt)
 
 			if m1 and m2:
@@ -310,19 +318,13 @@
 	def try_link():
 		if 'system' in params['lib']:
 			self.check_cxx(
-			 fragment="\n".join([
-			  '#include <boost/system/error_code.hpp>',
-			  'int main() { boost::system::error_code c; }',
-			 ]),
+			 fragment=BOOST_SYSTEM_CODE,
 			 use=var,
 			 execute=False,
 			)
 		if 'thread' in params['lib']:
 			self.check_cxx(
-			 fragment="\n".join([
-			  '#include <boost/thread.hpp>',
-			  'int main() { boost::thread t; }',
-			 ]),
+			 fragment=BOOST_THREAD_CODE,
 			 use=var,
 			 execute=False,
 			)
diff --git a/.waf-tools/default-compiler-flags.py b/.waf-tools/default-compiler-flags.py
index 299493a..9f7843e 100644
--- a/.waf-tools/default-compiler-flags.py
+++ b/.waf-tools/default-compiler-flags.py
@@ -12,14 +12,24 @@
 
 def configure(conf):
     areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
+    defaultFlags = []
+
+    if conf.options.use_cxx11:
+        defaultFlags += ['-std=c++0x', '-std=c++11']
+    else:
+        defaultFlags += ['-std=c++03']
+
+    defaultFlags += ['-pedantic', '-Wall', '-Wno-long-long']
+
     if conf.options.debug:
         conf.define('_DEBUG', 1)
-        defaultFlags = ['-O0', '-g3',
-                        '-Werror',
-                        '-Wall',
-                        '-fcolor-diagnostics', # only clang supports
+        defaultFlags += ['-O0',
+                         '-Og', # gcc >= 4.8
+                         '-g3',
+                         '-fcolor-diagnostics', # clang
+                         '-fdiagnostics-color', # gcc >= 4.9
+                         '-Werror'
                         ]
-
         if areCustomCxxflagsPresent:
             missingFlags = [x for x in defaultFlags if x not in conf.env.CXXFLAGS]
             if len(missingFlags) > 0:
@@ -27,11 +37,11 @@
                           % " ".join(conf.env.CXXFLAGS))
                 Logs.warn("Default flags '%s' are not activated" % " ".join(missingFlags))
         else:
-            conf.add_supported_cxxflags(cxxflags=defaultFlags)
+            conf.add_supported_cxxflags(defaultFlags)
     else:
-        defaultFlags = ['-O2', '-g', '-Wall']
+        defaultFlags += ['-O2', '-g']
         if not areCustomCxxflagsPresent:
-            conf.add_supported_cxxflags(cxxflags=defaultFlags)
+            conf.add_supported_cxxflags(defaultFlags)
 
 @Configure.conf
 def add_supported_cxxflags(self, cxxflags):
@@ -45,5 +55,5 @@
         if self.check_cxx(cxxflags=[flag], mandatory=False):
             supportedFlags += [flag]
 
-    self.end_msg(' '.join (supportedFlags))
+    self.end_msg(' '.join(supportedFlags))
     self.env.CXXFLAGS = supportedFlags + self.env.CXXFLAGS
diff --git a/daemon/core/face-uri.cpp b/daemon/core/face-uri.cpp
index 5da35cd..5cfaf72 100644
--- a/daemon/core/face-uri.cpp
+++ b/daemon/core/face-uri.cpp
@@ -24,6 +24,7 @@
 
 #include "face-uri.hpp"
 #include "core/logger.hpp"
+
 #ifdef HAVE_PCAP
 #include "face/ethernet.hpp"
 #endif // HAVE_PCAP
diff --git a/daemon/core/logger.hpp b/daemon/core/logger.hpp
index 552cb11..907ce7e 100644
--- a/daemon/core/logger.hpp
+++ b/daemon/core/logger.hpp
@@ -41,7 +41,7 @@
   LOG_DEBUG          = 4, // debug messages
   LOG_TRACE          = 5, // trace messages (most verbose)
   // LOG_FATAL is not a level and is logged unconditionally
-  LOG_ALL            = 255, // all messages
+  LOG_ALL            = 255 // all messages
 };
 
 class Logger
@@ -81,7 +81,6 @@
     m_moduleName = name;
   }
 
-
   /// \brief return a string representation of time since epoch: seconds.microseconds
   static std::string
   now()
@@ -89,13 +88,11 @@
     using namespace ndn::time;
 
     static const microseconds::rep ONE_SECOND = 1000000;
-
-    // 10 (whole seconds) + '.' + 6 (fraction) + 1 (\0)
-    char buffer[10 + 1 + 6 + 1];
-
     microseconds::rep microseconds_since_epoch =
       duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
 
+    // 10 (whole seconds) + '.' + 6 (fraction) + 1 (\0)
+    char buffer[10 + 1 + 6 + 1];
     ::snprintf(buffer, sizeof(buffer), "%lld.%06lld",
                static_cast<long long int>(microseconds_since_epoch / ONE_SECOND),
                static_cast<long long int>(microseconds_since_epoch % ONE_SECOND));
@@ -126,26 +123,26 @@
 
 namespace nfd {
 
-#define NFD_LOG_INIT(name)                                              \
-static nfd::Logger& g_logger = nfd::LoggerFactory::create(name);
+#define NFD_LOG_INIT(name) \
+static nfd::Logger& g_logger = nfd::LoggerFactory::create(name)
 
-#define NFD_LOG_INCLASS_DECLARE()               \
-static nfd::Logger& g_logger;
+#define NFD_LOG_INCLASS_DECLARE() \
+static nfd::Logger& g_logger
 
-#define NFD_LOG_INCLASS_DEFINE(cls, name)                       \
-nfd::Logger& cls::g_logger = nfd::LoggerFactory::create(name);
+#define NFD_LOG_INCLASS_DEFINE(cls, name) \
+nfd::Logger& cls::g_logger = nfd::LoggerFactory::create(name)
 
-#define NFD_LOG_INCLASS_TEMPLATE_DEFINE(cls, name)                      \
-template<class T>                                                       \
-nfd::Logger& cls<T>::g_logger = nfd::LoggerFactory::create(name);
+#define NFD_LOG_INCLASS_TEMPLATE_DEFINE(cls, name) \
+template<class T>                                  \
+nfd::Logger& cls<T>::g_logger = nfd::LoggerFactory::create(name)
 
 #define NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(cls, specialization, name) \
-template<>                                                              \
-nfd::Logger& cls<specialization>::g_logger = nfd::LoggerFactory::create(name);
+template<>                                                                        \
+nfd::Logger& cls<specialization>::g_logger = nfd::LoggerFactory::create(name)
 
 #define NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(cls, s1, s2, name) \
-template<>                                                              \
-nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name);
+template<>                                                                 \
+nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name)
 
 
 #define NFD_LOG(level, expression)                                      \
diff --git a/daemon/core/network-interface.cpp b/daemon/core/network-interface.cpp
index c8e4046..df47ac5 100644
--- a/daemon/core/network-interface.cpp
+++ b/daemon/core/network-interface.cpp
@@ -40,9 +40,9 @@
 #error Platform not supported
 #endif
 
-namespace nfd {
+NFD_LOG_INIT("NetworkInterfaceInfo");
 
-NFD_LOG_INIT("NetworkInterfaceInfo")
+namespace nfd {
 
 std::list< shared_ptr<NetworkInterfaceInfo> >
 listNetworkInterfaces()
diff --git a/daemon/face/datagram-face.hpp b/daemon/face/datagram-face.hpp
index 7669e72..7815eae 100644
--- a/daemon/face/datagram-face.hpp
+++ b/daemon/face/datagram-face.hpp
@@ -94,12 +94,12 @@
 protected:
   shared_ptr<typename protocol::socket> m_socket;
   uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
-
   bool m_hasBeenUsedRecently;
 
   NFD_LOG_INCLASS_DECLARE();
 };
 
+
 template <class T>
 inline
 DatagramFace<T>::DatagramFace(const FaceUri& remoteUri, const FaceUri& localUri,
diff --git a/daemon/face/ethernet-face.cpp b/daemon/face/ethernet-face.cpp
index 02cc041..fb278d3 100644
--- a/daemon/face/ethernet-face.cpp
+++ b/daemon/face/ethernet-face.cpp
@@ -38,7 +38,7 @@
 
 namespace nfd {
 
-NFD_LOG_INIT("EthernetFace")
+NFD_LOG_INIT("EthernetFace");
 
 EthernetFace::EthernetFace(const shared_ptr<boost::asio::posix::stream_descriptor>& socket,
                            const shared_ptr<NetworkInterfaceInfo>& interface,
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index 894f769..6809e6c 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -32,7 +32,7 @@
 
 namespace nfd {
 
-NFD_LOG_INIT("EthernetFactory")
+NFD_LOG_INIT("EthernetFactory");
 
 shared_ptr<EthernetFace>
 EthernetFactory::createMulticastFace(const shared_ptr<NetworkInterfaceInfo> &interface,
diff --git a/daemon/face/ethernet.cpp b/daemon/face/ethernet.cpp
index ee30aca..1aeaca6 100644
--- a/daemon/face/ethernet.cpp
+++ b/daemon/face/ethernet.cpp
@@ -42,22 +42,34 @@
 Address
 Address::fromString(const std::string& str)
 {
+  unsigned short temp[ADDR_LEN];
+  char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
+  int n = 0; // num of chars read from the input string
+
+  // ISO C++98 does not support the 'hh' type modifier
+  /// \todo use SCNx8 (cinttypes) when we enable C++11
+  int ret = ::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
+                     &temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
+                     &temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
+
+  if (ret < 11 || static_cast<size_t>(n) != str.length())
+    return Address();
+
   Address a;
-  int n, ret;
+  for (size_t i = 0; i < ADDR_LEN; ++i)
+    {
+      // check that all separators are actually the same char (: or -)
+      if (i < 5 && sep[i][0] != sep[0][0])
+        return Address();
 
-  // colon-separated
-  ret = ::sscanf(str.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx%n",
-                 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &n);
-  if (ret >= 6 && str.c_str()[n] == '\0')
-    return a;
+      // check that each value fits into a uint8_t
+      if (temp[i] > 0xFF)
+        return Address();
 
-  // dash-separated
-  ret = ::sscanf(str.c_str(), "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx%n",
-                 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &n);
-  if (ret >= 6 && str.c_str()[n] == '\0')
-    return a;
+      a[i] = static_cast<uint8_t>(temp[i]);
+    }
 
-  return Address();
+  return a;
 }
 
 std::ostream&
diff --git a/daemon/face/face.cpp b/daemon/face/face.cpp
index d4d198f..d0d42db 100644
--- a/daemon/face/face.cpp
+++ b/daemon/face/face.cpp
@@ -27,8 +27,6 @@
 
 namespace nfd {
 
-NFD_LOG_INIT("Face")
-
 static inline void
 increaseCounter(FaceCounter& counter)
 {
diff --git a/tests/face/ethernet-address.cpp b/tests/face/ethernet-address.cpp
index 92626b2..d9e1b42 100644
--- a/tests/face/ethernet-address.cpp
+++ b/tests/face/ethernet-address.cpp
@@ -57,6 +57,8 @@
                     ethernet::getBroadcastAddress());
   BOOST_CHECK_EQUAL(ethernet::Address::fromString("de:ad:be:ef:1:2"),
                     ethernet::Address(0xde, 0xad, 0xbe, 0xef, 0x01, 0x02));
+  BOOST_CHECK_EQUAL(ethernet::Address::fromString("DE:AD:BE:EF:1:2"),
+                    ethernet::Address(0xde, 0xad, 0xbe, 0xef, 0x01, 0x02));
 
   // malformed inputs
   BOOST_CHECK_EQUAL(ethernet::Address::fromString("01.23.45.67.89.ab"),
@@ -69,6 +71,8 @@
                     ethernet::Address());
   BOOST_CHECK_EQUAL(ethernet::Address::fromString("01:23:45:67:89:ab:cd"),
                     ethernet::Address());
+  BOOST_CHECK_EQUAL(ethernet::Address::fromString("01:23:45:67-89-ab"),
+                    ethernet::Address());
   BOOST_CHECK_EQUAL(ethernet::Address::fromString("qw-er-ty-12-34-56"),
                     ethernet::Address());
   BOOST_CHECK_EQUAL(ethernet::Address::fromString("this-is-not-an-ethernet-address"),
diff --git a/tests/face/ndnlp.cpp b/tests/face/ndnlp.cpp
index 7681e86..66a1c84 100644
--- a/tests/face/ndnlp.cpp
+++ b/tests/face/ndnlp.cpp
@@ -28,6 +28,8 @@
 
 #include "tests/test-common.hpp"
 
+#include <boost/scoped_array.hpp>
+
 namespace nfd {
 namespace tests {
 
@@ -161,9 +163,9 @@
   Block
   makeBlock(size_t valueLength)
   {
-    uint8_t blockValue[valueLength];
-    memset(blockValue, 0xcc, sizeof(blockValue));
-    return ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
+    boost::scoped_array<uint8_t> blockValue(new uint8_t[valueLength]);
+    memset(blockValue.get(), 0xcc, valueLength);
+    return ndn::dataBlock(0x01, blockValue.get(), valueLength);
   }
 
 protected:
diff --git a/tests/mgmt/validation-common.cpp b/tests/mgmt/validation-common.cpp
index 2e4cce9..6065c27 100644
--- a/tests/mgmt/validation-common.cpp
+++ b/tests/mgmt/validation-common.cpp
@@ -44,7 +44,7 @@
   m_keys.deleteIdentity(s_identityName);
 }
 
-BOOST_GLOBAL_FIXTURE(CommandIdentityGlobalFixture);
+BOOST_GLOBAL_FIXTURE(CommandIdentityGlobalFixture)
 
 } // namespace tests
 } // namespace nfd
diff --git a/wscript b/wscript
index 9eab3b1..9681089 100644
--- a/wscript
+++ b/wscript
@@ -37,6 +37,8 @@
              tooldir=['.waf-tools'])
 
     nfdopt = opt.add_option_group('NFD Options')
+    nfdopt.add_option('--with-c++11', action='store_true', default=False, dest='use_cxx11',
+                      help='''Enable C++11 mode (experimental, may not work)''')
     nfdopt.add_option('--with-tests', action='store_true', default=False,
                       dest='with_tests', help='''Build unit tests''')
     nfdopt.add_option('--with-other-tests', action='store_true', default=False,