am f9b9693b: Merge "liblog: logcat: colored output."
* commit 'f9b9693bab9d6d614ac0da12734dca7bab487c44': liblog: logcat: colored output.
This commit is contained in:
commit
e70851f8a8
3 changed files with 81 additions and 32 deletions
|
|
@ -36,6 +36,7 @@ typedef enum {
|
||||||
FORMAT_TIME,
|
FORMAT_TIME,
|
||||||
FORMAT_THREADTIME,
|
FORMAT_THREADTIME,
|
||||||
FORMAT_LONG,
|
FORMAT_LONG,
|
||||||
|
FORMAT_COLOR,
|
||||||
} AndroidLogPrintFormat;
|
} AndroidLogPrintFormat;
|
||||||
|
|
||||||
typedef struct AndroidLogFormat_t AndroidLogFormat;
|
typedef struct AndroidLogFormat_t AndroidLogFormat;
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,12 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <log/logd.h>
|
#include <log/logd.h>
|
||||||
#include <log/logprint.h>
|
#include <log/logprint.h>
|
||||||
|
|
@ -39,8 +41,23 @@ struct AndroidLogFormat_t {
|
||||||
android_LogPriority global_pri;
|
android_LogPriority global_pri;
|
||||||
FilterInfo *filters;
|
FilterInfo *filters;
|
||||||
AndroidLogPrintFormat format;
|
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)
|
static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
|
||||||
{
|
{
|
||||||
FilterInfo *p_ret;
|
FilterInfo *p_ret;
|
||||||
|
|
@ -110,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(
|
static android_LogPriority filterPriForTag(
|
||||||
AndroidLogFormat *p_format, const char *tag)
|
AndroidLogFormat *p_format, const char *tag)
|
||||||
{
|
{
|
||||||
|
|
@ -149,6 +183,7 @@ AndroidLogFormat *android_log_format_new()
|
||||||
|
|
||||||
p_ret->global_pri = ANDROID_LOG_VERBOSE;
|
p_ret->global_pri = ANDROID_LOG_VERBOSE;
|
||||||
p_ret->format = FORMAT_BRIEF;
|
p_ret->format = FORMAT_BRIEF;
|
||||||
|
p_ret->colored_output = false;
|
||||||
|
|
||||||
return p_ret;
|
return p_ret;
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +209,10 @@ void android_log_format_free(AndroidLogFormat *p_format)
|
||||||
void android_log_setPrintFormat(AndroidLogFormat *p_format,
|
void android_log_setPrintFormat(AndroidLogFormat *p_format,
|
||||||
AndroidLogPrintFormat format)
|
AndroidLogPrintFormat format)
|
||||||
{
|
{
|
||||||
p_format->format=format;
|
if (format == FORMAT_COLOR)
|
||||||
|
p_format->colored_output = true;
|
||||||
|
else
|
||||||
|
p_format->format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -192,6 +230,7 @@ AndroidLogPrintFormat android_log_formatFromString(const char * formatString)
|
||||||
else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME;
|
else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME;
|
||||||
else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME;
|
else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME;
|
||||||
else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG;
|
else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG;
|
||||||
|
else if (strcmp(formatString, "color") == 0) format = FORMAT_COLOR;
|
||||||
else format = FORMAT_OFF;
|
else format = FORMAT_OFF;
|
||||||
|
|
||||||
return format;
|
return format;
|
||||||
|
|
@ -698,6 +737,8 @@ char *android_log_formatLogLine (
|
||||||
char * ret = NULL;
|
char * ret = NULL;
|
||||||
|
|
||||||
priChar = filterPriToChar(entry->priority);
|
priChar = filterPriToChar(entry->priority);
|
||||||
|
size_t prefixLen = 0, suffixLen = 0;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the current date/time in pretty form
|
* Get the current date/time in pretty form
|
||||||
|
|
@ -719,73 +760,80 @@ char *android_log_formatLogLine (
|
||||||
/*
|
/*
|
||||||
* Construct a buffer containing the log header and log message.
|
* 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) {
|
switch (p_format->format) {
|
||||||
case FORMAT_TAG:
|
case FORMAT_TAG:
|
||||||
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
|
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
|
||||||
"%c/%-8s: ", priChar, entry->tag);
|
"%c/%-8s: ", priChar, entry->tag);
|
||||||
strcpy(suffixBuf, "\n"); suffixLen = 1;
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
case FORMAT_PROCESS:
|
case FORMAT_PROCESS:
|
||||||
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
|
len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen,
|
||||||
"%c(%5d) ", priChar, entry->pid);
|
|
||||||
suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
|
|
||||||
" (%s)\n", entry->tag);
|
" (%s)\n", entry->tag);
|
||||||
|
suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen);
|
||||||
|
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
|
||||||
|
"%c(%5d) ", priChar, entry->pid);
|
||||||
break;
|
break;
|
||||||
case FORMAT_THREAD:
|
case FORMAT_THREAD:
|
||||||
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
|
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
|
||||||
"%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
|
"%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
|
||||||
strcpy(suffixBuf, "\n");
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
suffixLen = 1;
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
case FORMAT_RAW:
|
case FORMAT_RAW:
|
||||||
prefixBuf[0] = 0;
|
prefixBuf[prefixLen] = 0;
|
||||||
prefixLen = 0;
|
len = 0;
|
||||||
strcpy(suffixBuf, "\n");
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
suffixLen = 1;
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
case FORMAT_TIME:
|
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,
|
"%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
|
||||||
priChar, entry->tag, entry->pid);
|
priChar, entry->tag, entry->pid);
|
||||||
strcpy(suffixBuf, "\n");
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
suffixLen = 1;
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
case FORMAT_THREADTIME:
|
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,
|
"%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
|
||||||
entry->pid, entry->tid, priChar, entry->tag);
|
entry->pid, entry->tid, priChar, entry->tag);
|
||||||
strcpy(suffixBuf, "\n");
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
suffixLen = 1;
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
case FORMAT_LONG:
|
case FORMAT_LONG:
|
||||||
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
|
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
|
||||||
"[ %s.%03ld %5d:%5d %c/%-8s ]\n",
|
"[ %s.%03ld %5d:%5d %c/%-8s ]\n",
|
||||||
timeBuf, entry->tv_nsec / 1000000, entry->pid,
|
timeBuf, entry->tv_nsec / 1000000, entry->pid,
|
||||||
entry->tid, priChar, entry->tag);
|
entry->tid, priChar, entry->tag);
|
||||||
strcpy(suffixBuf, "\n\n");
|
strcpy(suffixBuf + suffixLen, "\n\n");
|
||||||
suffixLen = 2;
|
suffixLen += 2;
|
||||||
prefixSuffixIsHeaderFooter = 1;
|
prefixSuffixIsHeaderFooter = 1;
|
||||||
break;
|
break;
|
||||||
case FORMAT_BRIEF:
|
case FORMAT_BRIEF:
|
||||||
default:
|
default:
|
||||||
prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
|
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
|
||||||
"%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
|
"%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
|
||||||
strcpy(suffixBuf, "\n");
|
strcpy(suffixBuf + suffixLen, "\n");
|
||||||
suffixLen = 1;
|
++suffixLen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* snprintf has a weird return value. It returns what would have been
|
/* 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
|
* written given a large enough buffer. In the case that the prefix is
|
||||||
* longer then our buffer(128), it messes up the calculations below
|
* longer then our buffer(128), it messes up the calculations below
|
||||||
* possibly causing heap corruption. To avoid this we double check and
|
* possibly causing heap corruption. To avoid this we double check and
|
||||||
* set the length at the maximum (size minus null byte)
|
* set the length at the maximum (size minus null byte)
|
||||||
*/
|
*/
|
||||||
if(prefixLen >= sizeof(prefixBuf))
|
prefixLen += MIN(len, sizeof(prefixBuf) - prefixLen);
|
||||||
prefixLen = sizeof(prefixBuf) - 1;
|
suffixLen = MIN(suffixLen, sizeof(suffixLen));
|
||||||
if(suffixLen >= sizeof(suffixBuf))
|
|
||||||
suffixLen = sizeof(suffixBuf) - 1;
|
|
||||||
|
|
||||||
/* the following code is tragically unreadable */
|
/* the following code is tragically unreadable */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,8 +219,8 @@ static void show_help(const char *cmd)
|
||||||
" -f <filename> Log to file. Default to stdout\n"
|
" -f <filename> Log to file. Default to stdout\n"
|
||||||
" -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n"
|
" -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n"
|
||||||
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
|
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
|
||||||
" -v <format> Sets the log print format, where <format> is one of:\n\n"
|
" -v <format> Sets the log print format, where <format> is:\n\n"
|
||||||
" brief process tag thread raw time threadtime long\n\n"
|
" brief color long process raw tag thread threadtime time\n\n"
|
||||||
" -c clear (flush) the entire log and exit\n"
|
" -c clear (flush) the entire log and exit\n"
|
||||||
" -d dump the log and then exit (don't block)\n"
|
" -d dump the log and then exit (don't block)\n"
|
||||||
" -t <count> print only the most recent <count> lines (implies -d)\n"
|
" -t <count> print only the most recent <count> lines (implies -d)\n"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue