//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// 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>
#ifndef ARDUINO
-
+#ifndef __TIZEN__
void OCLogConfig(oc_log_ctx_t *ctx) {
logCtx = ctx;
}
}
void OCLogShutdown() {
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
if (logCtx && logCtx->destroy)
{
logCtx->destroy(logCtx);
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);
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
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
}
/**
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;
OCLog(level, tag, lineBuffer);
}
}
-
+#endif //__TIZEN__
#else
/**
* Initialize the serial logger for Arduino
* @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;
}
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')
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
-
-