diff options
Diffstat (limited to 'liblog/logprint.c')
-rw-r--r-- | liblog/logprint.c | 235 |
1 files changed, 85 insertions, 150 deletions
diff --git a/liblog/logprint.c b/liblog/logprint.c index a7480d5..9b5a543 100644 --- a/liblog/logprint.c +++ b/liblog/logprint.c @@ -17,14 +17,16 @@ #define _GNU_SOURCE /* for asprintf */ +#include <arpa/inet.h> +#include <assert.h> #include <ctype.h> -#include <stdio.h> #include <errno.h> -#include <stdlib.h> +#include <stdbool.h> #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <assert.h> -#include <arpa/inet.h> +#include <sys/param.h> #include <log/logd.h> #include <log/logprint.h> @@ -39,8 +41,23 @@ struct AndroidLogFormat_t { android_LogPriority global_pri; FilterInfo *filters; AndroidLogPrintFormat format; + bool colored_output; }; +/* + * gnome-terminal color tags + * See http://misc.flogisoft.com/bash/tip_colors_and_formatting + * for ideas on how to set the forground color of the text for xterm. + * The color manipulation character stream is defined as: + * ESC [ 3 8 ; 5 ; <color#> m + */ +#define ANDROID_COLOR_BLUE 75 +#define ANDROID_COLOR_DEFAULT 231 +#define ANDROID_COLOR_GREEN 40 +#define ANDROID_COLOR_ORANGE 166 +#define ANDROID_COLOR_RED 196 +#define ANDROID_COLOR_YELLOW 226 + static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri) { FilterInfo *p_ret; @@ -52,15 +69,7 @@ static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri) return p_ret; } -static void filterinfo_free(FilterInfo *p_info) -{ - if (p_info == NULL) { - return; - } - - free(p_info->mTag); - p_info->mTag = NULL; -} +/* balance to above, filterinfo_free left unimplemented */ /* * Note: also accepts 0-9 priorities @@ -118,6 +127,23 @@ static char filterPriToChar (android_LogPriority pri) } } +static int colorFromPri (android_LogPriority pri) +{ + switch (pri) { + case ANDROID_LOG_VERBOSE: return ANDROID_COLOR_DEFAULT; + case ANDROID_LOG_DEBUG: return ANDROID_COLOR_BLUE; + case ANDROID_LOG_INFO: return ANDROID_COLOR_GREEN; + case ANDROID_LOG_WARN: return ANDROID_COLOR_ORANGE; + case ANDROID_LOG_ERROR: return ANDROID_COLOR_RED; + case ANDROID_LOG_FATAL: return ANDROID_COLOR_RED; + case ANDROID_LOG_SILENT: return ANDROID_COLOR_DEFAULT; + + case ANDROID_LOG_DEFAULT: + case ANDROID_LOG_UNKNOWN: + default: return ANDROID_COLOR_DEFAULT; + } +} + static android_LogPriority filterPriForTag( AndroidLogFormat *p_format, const char *tag) { @@ -139,23 +165,6 @@ static android_LogPriority filterPriForTag( return p_format->global_pri; } -/** for debugging */ -static void dumpFilters(AndroidLogFormat *p_format) -{ - FilterInfo *p_fi; - - for (p_fi = p_format->filters ; p_fi != NULL ; p_fi = p_fi->p_next) { - char cPri = filterPriToChar(p_fi->mPri); - if (p_fi->mPri == ANDROID_LOG_DEFAULT) { - cPri = filterPriToChar(p_format->global_pri); - } - fprintf(stderr,"%s:%c\n", p_fi->mTag, cPri); - } - - fprintf(stderr,"*:%c\n", filterPriToChar(p_format->global_pri)); - -} - /** * returns 1 if this log line should be printed based on its priority * and tag, and 0 if it should not @@ -174,6 +183,7 @@ AndroidLogFormat *android_log_format_new() p_ret->global_pri = ANDROID_LOG_VERBOSE; p_ret->format = FORMAT_BRIEF; + p_ret->colored_output = false; return p_ret; } @@ -199,7 +209,10 @@ void android_log_format_free(AndroidLogFormat *p_format) void android_log_setPrintFormat(AndroidLogFormat *p_format, AndroidLogPrintFormat format) { - p_format->format=format; + if (format == FORMAT_COLOR) + p_format->colored_output = true; + else + p_format->format = format; } /** @@ -217,6 +230,7 @@ AndroidLogPrintFormat android_log_formatFromString(const char * formatString) else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME; else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME; else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG; + else if (strcmp(formatString, "color") == 0) format = FORMAT_COLOR; else format = FORMAT_OFF; return format; @@ -234,7 +248,6 @@ AndroidLogPrintFormat android_log_formatFromString(const char * formatString) int android_log_addFilterRule(AndroidLogFormat *p_format, const char *filterExpression) { - size_t i=0; size_t tagNameLength; android_LogPriority pri = ANDROID_LOG_DEFAULT; @@ -713,18 +726,19 @@ char *android_log_formatLogLine ( const AndroidLogEntry *entry, size_t *p_outLength) { -#if defined(HAVE_LOCALTIME_R) +#if !defined(_WIN32) struct tm tmBuf; #endif struct tm* ptm; char timeBuf[32]; - char headerBuf[128]; char prefixBuf[128], suffixBuf[128]; char priChar; int prefixSuffixIsHeaderFooter = 0; char * ret = NULL; priChar = filterPriToChar(entry->priority); + size_t prefixLen = 0, suffixLen = 0; + size_t len; /* * Get the current date/time in pretty form @@ -735,7 +749,7 @@ char *android_log_formatLogLine ( * in the time stamp. Don't use forward slashes, parenthesis, * brackets, asterisks, or other special chars here. */ -#if defined(HAVE_LOCALTIME_R) +#if !defined(_WIN32) ptm = localtime_r(&(entry->tv_sec), &tmBuf); #else ptm = localtime(&(entry->tv_sec)); @@ -746,78 +760,84 @@ char *android_log_formatLogLine ( /* * Construct a buffer containing the log header and log message. */ - size_t prefixLen, suffixLen; + if (p_format->colored_output) { + prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "\x1B[38;5;%dm", + colorFromPri(entry->priority)); + prefixLen = MIN(prefixLen, sizeof(prefixBuf)); + suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), "\x1B[0m"); + suffixLen = MIN(suffixLen, sizeof(suffixBuf)); + } switch (p_format->format) { case FORMAT_TAG: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c/%-8s: ", priChar, entry->tag); - strcpy(suffixBuf, "\n"); suffixLen = 1; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; case FORMAT_PROCESS: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), - "%c(%5d) ", priChar, entry->pid); - suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), + len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen, " (%s)\n", entry->tag); + suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen); + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, + "%c(%5d) ", priChar, entry->pid); break; case FORMAT_THREAD: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c(%5d:%5d) ", priChar, entry->pid, entry->tid); - strcpy(suffixBuf, "\n"); - suffixLen = 1; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; case FORMAT_RAW: - prefixBuf[0] = 0; - prefixLen = 0; - strcpy(suffixBuf, "\n"); - suffixLen = 1; + prefixBuf[prefixLen] = 0; + len = 0; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; case FORMAT_TIME: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000, priChar, entry->tag, entry->pid); - strcpy(suffixBuf, "\n"); - suffixLen = 1; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; case FORMAT_THREADTIME: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000, entry->pid, entry->tid, priChar, entry->tag); - strcpy(suffixBuf, "\n"); - suffixLen = 1; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; case FORMAT_LONG: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "[ %s.%03ld %5d:%5d %c/%-8s ]\n", timeBuf, entry->tv_nsec / 1000000, entry->pid, entry->tid, priChar, entry->tag); - strcpy(suffixBuf, "\n\n"); - suffixLen = 2; + strcpy(suffixBuf + suffixLen, "\n\n"); + suffixLen += 2; prefixSuffixIsHeaderFooter = 1; break; case FORMAT_BRIEF: default: - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), + len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid); - strcpy(suffixBuf, "\n"); - suffixLen = 1; + strcpy(suffixBuf + suffixLen, "\n"); + ++suffixLen; break; } + /* snprintf has a weird return value. It returns what would have been * written given a large enough buffer. In the case that the prefix is * longer then our buffer(128), it messes up the calculations below * possibly causing heap corruption. To avoid this we double check and * set the length at the maximum (size minus null byte) */ - if(prefixLen >= sizeof(prefixBuf)) - prefixLen = sizeof(prefixBuf) - 1; - if(suffixLen >= sizeof(suffixBuf)) - suffixLen = sizeof(suffixBuf) - 1; + prefixLen += MIN(len, sizeof(prefixBuf) - prefixLen); + suffixLen = MIN(suffixLen, sizeof(suffixLen)); /* the following code is tragically unreadable */ size_t numLines; - size_t i; char *p; size_t bufferSize; const char *pm; @@ -938,88 +958,3 @@ done: return ret; } - - - -void logprint_run_tests() -{ -#if 0 - - fprintf(stderr, "tests disabled\n"); - -#else - - int err; - const char *tag; - AndroidLogFormat *p_format; - - p_format = android_log_format_new(); - - fprintf(stderr, "running tests\n"); - - tag = "random"; - - android_log_addFilterRule(p_format,"*:i"); - - assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0); - android_log_addFilterRule(p_format, "*"); - assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0); - android_log_addFilterRule(p_format, "*:v"); - assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0); - android_log_addFilterRule(p_format, "*:i"); - assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0); - - android_log_addFilterRule(p_format, "random"); - assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0); - android_log_addFilterRule(p_format, "random:v"); - assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0); - android_log_addFilterRule(p_format, "random:d"); - assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0); - android_log_addFilterRule(p_format, "random:w"); - assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0); - - android_log_addFilterRule(p_format, "crap:*"); - assert (ANDROID_LOG_VERBOSE== filterPriForTag(p_format, "crap")); - assert(android_log_shouldPrintLine(p_format, "crap", ANDROID_LOG_VERBOSE) > 0); - - // invalid expression - err = android_log_addFilterRule(p_format, "random:z"); - assert (err < 0); - assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random")); - assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0); - - // Issue #550946 - err = android_log_addFilterString(p_format, " "); - assert(err == 0); - assert(ANDROID_LOG_WARN == filterPriForTag(p_format, "random")); - - // note trailing space - err = android_log_addFilterString(p_format, "*:s random:d "); - assert(err == 0); - assert(ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random")); - - err = android_log_addFilterString(p_format, "*:s random:z"); - assert(err < 0); - - -#if 0 - char *ret; - char defaultBuffer[512]; - - ret = android_log_formatLogLine(p_format, - defaultBuffer, sizeof(defaultBuffer), 0, ANDROID_LOG_ERROR, 123, - 123, 123, "random", "nofile", strlen("Hello"), "Hello", NULL); -#endif - - - fprintf(stderr, "tests complete\n"); -#endif -} |