Merge remote-tracking branch 'origin/routing-manager'
[platform/upstream/iotivity.git] / resource / csdk / logger / src / logger.c
index ad9afd2..8e21e33 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+// Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1b, Real-time extensions
+// (IEEE Std 1003.1b-1993) specification
+//
+// For this specific file, see use of clock_gettime,
+// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
+// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+// Platform check can be extended to check and/or define more, or could be
+// moved into a config.h
+#if !defined(__ARDUINO__) && !defined(ARDUINO)
+#define HAVE_UNISTD_H 1
+#endif
+
+// Pull in _POSIX_TIMERS feature test macro to check for
+// clock_gettime() support.
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+
+// if we have unistd.h, we're a Unix system
+#include <time.h>
+#include <sys/time.h>
+#endif
 
 #include "logger.h"
 #include "string.h"
 #include "oc_logger.h"
 #include "oc_console_logger.h"
 
+#ifndef __TIZEN__
 static oc_log_ctx_t *logCtx = 0;
 
 static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO, OC_LOG_WARNING, OC_LOG_ERROR, OC_LOG_FATAL};
 
+#endif
 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1;  // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
 
 // Convert LogLevel to platform-specific severity level.  Store in PROGMEM on Arduino
 #ifdef __ANDROID__
     static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
-#elif defined __linux__
+#elif defined(__linux__) || defined(__APPLE__)
     static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
 #elif defined ARDUINO
     #include <stdarg.h>
@@ -60,7 +89,7 @@ static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1;  // Show 16 bytes, 2
 
 
 #ifndef ARDUINO
-
+#ifndef __TIZEN__
 void OCLogConfig(oc_log_ctx_t *ctx) {
     logCtx = ctx;
 }
@@ -70,7 +99,7 @@ void OCLogInit() {
 }
 
 void OCLogShutdown() {
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
     if (logCtx && logCtx->destroy)
     {
         logCtx->destroy(logCtx);
@@ -90,8 +119,7 @@ void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
     if (!format || !tag) {
         return;
     }
-    char buffer[MAX_LOG_V_BUFFER_SIZE];
-    memset(buffer, 0, sizeof buffer);
+    char buffer[MAX_LOG_V_BUFFER_SIZE] = {};
     va_list args;
     va_start(args, format);
     vsnprintf(buffer, sizeof buffer - 1, format, args);
@@ -99,6 +127,34 @@ void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
     OCLog(level, tag, buffer);
 }
 
+static void osalGetTime(int *min,int *sec, int *ms)
+{
+    if (min && sec && ms)
+    {
+#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
+        struct timespec when = {0};
+        clockid_t clk = CLOCK_REALTIME;
+#ifdef CLOCK_REALTIME_COARSE
+        clk = CLOCK_REALTIME_COARSE;
+#endif
+        if (!clock_gettime(clk, &when))
+        {
+            *min = (when.tv_sec / 60) % 60;
+            *sec = when.tv_sec % 60;
+            *ms = when.tv_nsec / 1000000;
+        }
+#else
+        struct timeval now;
+        if (!gettimeofday(&now, NULL))
+        {
+            *min = (now.tv_sec / 60) % 60;
+            *sec = now.tv_sec % 60;
+            *ms = now.tv_usec * 1000;
+        }
+#endif
+    }
+}
+
 /**
  * Output a log string with the specified priority level.
  * Only defined for Linux and Android
@@ -112,19 +168,23 @@ void OCLog(LogLevel level, const char * tag, const char * logStr) {
         return;
     }
 
-    #ifdef __ANDROID__
-        __android_log_write(LEVEL[level], tag, logStr);
-    #elif defined __linux__
-        if (logCtx && logCtx->write_level)
-        {
-            logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
+#ifdef __ANDROID__
+    __android_log_write(LEVEL[level], tag, logStr);
+#elif defined(__linux__) || defined(__APPLE__)
+    if (logCtx && logCtx->write_level)
+    {
+        logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
+    }
+    else
+    {
+        int min = 0;
+        int sec = 0;
+        int ms = 0;
+        osalGetTime(&min,&sec,&ms);
 
-        }
-        else
-        {
-            printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
-        }
-    #endif
+        printf("%02d:%02d.%03d %s: %s: %s\n", min, sec, ms, LEVEL[level], tag, logStr);
+    }
+#endif
 }
 
 /**
@@ -140,6 +200,8 @@ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint1
         return;
     }
 
+    // No idea why the static initialization won't work here, it seems the compiler is convinced
+    // that this is a variable-sized object.
     char lineBuffer[LINE_BUFFER_SIZE];
     memset(lineBuffer, 0, sizeof lineBuffer);
     int lineIndex = 0;
@@ -160,7 +222,7 @@ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint1
         OCLog(level, tag, lineBuffer);
     }
 }
-
+#endif //__TIZEN__
 #else
     /**
      * Initialize the serial logger for Arduino
@@ -273,7 +335,7 @@ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint1
      * @param tag    - Module name
      * @param format - variadic log string
      */
-    void OCLogv(LogLevel level, PROGMEM const char * tag, const char * format, ...)
+    void OCLogv(LogLevel level, PROGMEM const char * tag, PROGMEM const char * format, ...)
     {
         char buffer[LINE_BUFFER_SIZE];
         va_list ap;
@@ -291,7 +353,11 @@ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint1
         }
         Serial.print(F(": "));
 
+#ifdef __AVR__
+        vsnprintf_P(buffer, sizeof(buffer), format, ap);
+#else
         vsnprintf(buffer, sizeof(buffer), format, ap);
+#endif
         for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
         {
             if(*p == '\n')
@@ -303,50 +369,5 @@ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint1
         Serial.println();
         va_end(ap);
     }
-    /**
-     * Output a variable argument list log string with the specified priority level.
-     * Only defined for Arduino as depicted below.
-     *
-     * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
-     * @param tag    - Module name
-     * @param format - variadic log string
-     */
-    void OCLogv(LogLevel level, PROGMEM const char * tag, const __FlashStringHelper *format, ...)
-    {
-        char buffer[LINE_BUFFER_SIZE];
-        va_list ap;
-        va_start(ap, format);
-
-        GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
-        Serial.print(buffer);
-
-        char c;
-        Serial.print(F(": "));
-
-        while ((c = pgm_read_byte(tag))) {
-          Serial.write(c);
-          tag++;
-        }
-        Serial.print(F(": "));
-
-        #ifdef __AVR__
-            vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
-        #else
-            vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
-        #endif
-        for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
-        {
-            if(*p == '\n')
-            {
-                Serial.write('\r');
-            }
-            Serial.write(*p);
-        }
-        Serial.println();
-        va_end(ap);
-    }
-
 
 #endif
-
-