-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdebug.c
123 lines (117 loc) · 4.22 KB
/
debug.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#define _POSIX_C_SOURCE 201112L
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
static long pid = -1;
static bool color_enabled = false;
__attribute__((constructor(101))) static void
fp_dbg_init()
{
pid = (long) getpid();
color_enabled = isatty(STDOUT_FILENO) == 1;
#if 0
fprintf(stderr, "debugging setup: pid %ld, %s color\n", pid,
color_enabled ? "" : "no");
#endif
}
static bool
dbgchannel_enabled(const struct symbdbgchannel* chn, enum SymbiontChanClass c)
{
return (chn->flags & (1U << c)) > 0;
}
/* ANSI escape codes for colors. */
__attribute__((unused)) static const char* C_DGRAY = "\033[01;30m";
static const char* C_NORM = "\033[00m";
static const char* C_RED = "\033[01;31m";
static const char* C_YELLOW = "\033[01;33m";
__attribute__((unused)) static const char* C_GREEN = "\033[01;32m";
__attribute__((unused)) static const char* C_MAG = "\033[01;35m";
static const char* C_LBLUE = "\033[01;36m";
__attribute__((unused)) static const char* C_WHITE = "\033[01;27m";
static const char*
color(const enum SymbiontChanClass cls)
{
if(!color_enabled) { return ""; }
switch(cls) {
case SymbiontTrace: return C_WHITE;
case SymbiontWarn: return C_YELLOW;
case SymbiontErr: return C_RED;
case SymbiontFixme: return C_LBLUE;
}
assert(false);
return C_NORM;
}
void
symb_dbg(enum SymbiontChanClass type, const struct symbdbgchannel* channel,
const char* func, const char* format, ...)
{
va_list args;
va_start(args, format);
if(dbgchannel_enabled(channel, type)) {
const char* fixit = type==SymbiontFixme ? "-FIXME" : "";
printf("%s[%ld](%s%s) ", color(type), pid, func, fixit);
(void) vprintf(format, args);
printf("%s\n", color_enabled ? C_NORM : "");
}
va_end(args);
}
/* maps a string name to a class. there should be a one-to-one mapping from
* every entry in 'enum SymbiontChanClass' to this. */
static enum SymbiontChanClass
name_class(const char* name)
{
if(strncmp(name, "err", 3) == 0) { return SymbiontErr; }
if(strncmp(name, "warn", 4) == 0) { return SymbiontWarn; }
if(strncmp(name, "trace", 5) == 0) { return SymbiontTrace; }
if(strncmp(name, "fixme", 5) == 0) { return SymbiontFixme; }
/* hack. what do we do if they give us a class that isn't defined? well,
* since we use this to find the flag's position by bit-shifting, let's just
* do something we know will shit off the end of our flag sizes. that way,
* undefined classes are just silently ignored. */
return 64;
}
/* parses options of the form "chname=+a,-b,+c;chname2=+d,-c". */
void
symb_parse_options(struct symbdbgchannel* ch, const char* opt)
{
_Static_assert(sizeof(enum SymbiontChanClass) <= sizeof(unsigned),
"to make sure we can't shift beyond flags");
/* outer loop iterates over channels. channel names are separated by ';' */
for(const char* chan=opt; chan && chan!=(const char*)0x1;
chan=strchr(chan, ';')+1) {
/* extract a substring to make parsing easier. */
char* chopts = strdup(chan);
{ /* if there's another channel after, cut the string there. */
char* nextopt = strchr(chopts, ';');
if(nextopt) { *nextopt = '\0'; }
}
if(strncmp(chopts, ch->name, strlen(ch->name)) == 0) {
/* matched our channel name. now we want to parse the list of options,
* separated by commas, e.g.: "+x,-y,+blah,+abc" */
for(char* olist=strchr(chopts, '=')+1;
olist && olist != (const char*)0x1;
olist = strchr(olist, ',')+1) {
/* the "+1" gets rid of the minus or plus */
enum SymbiontChanClass cls = name_class(olist+1);
/* temporarily null out the subsequent options, for printing. */
char* optend = strchr(olist, ',');
if(optend) { *optend = '\0'; }
if(*olist == '+') {
fprintf(stderr, "[%ld] %s: enabling %s\n", pid, ch->name, olist+1);
ch->flags |= (1U<<(uint16_t)cls);
} else if(*olist == '-') {
fprintf(stderr, "[%ld] %s: disabling %s\n", pid, ch->name, olist+1);
ch->flags &= ~(1U<<(uint16_t)cls);
}
/* 'de-null' it. */
if(optend) { *optend = ','; }
}
}
free(chopts);
}
}