Coverage Report

Created: 2023-06-07 06:38

/src/clib/deps/debug/debug.c
Line
Count
Source (jump to first uncovered line)
1
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
#include <time.h>
6
#include <unistd.h>
7
#include "strdup/strdup.h"
8
#include "asprintf/asprintf.h"
9
#include "wildcardcmp/wildcardcmp.h"
10
#include "debug.h"
11
12
/**
13
 * Have we seeded `rand()`?
14
 */
15
16
static int seeded = 0;
17
18
/**
19
 * Log format.
20
 */
21
22
0
#define FMT "\x1B[3%dm%s\033[0m"
23
24
/**
25
 * ENV var delimiter.
26
 */
27
28
0
#define DELIMITER ","
29
30
/**
31
 * Check if the given `stream` is a TTY, and/or if
32
 * the environment variable `DEBUG_COLORS` has been
33
 * disabled.
34
 */
35
36
static int
37
0
use_colors(FILE *stream) {
38
  // only use color for a TTY
39
0
  int tty = isatty(fileno(stream));
40
0
  if (0 == tty) return 0;
41
  // check env
42
0
  char *colors = getenv("DEBUG_COLORS");
43
0
  if (!colors) return 1;
44
  // see: https://github.com/visionmedia/debug/blob/2.1.0/node.js#L49-L52
45
0
  if (0 == strcmp("0", colors)) return 0;
46
0
  if (0 == strncmp("no", colors, 2)) return 0;
47
0
  if (0 == strncmp("false", colors, 5)) return 0;
48
0
  if (0 == strncmp("disabled", colors, 8)) return 0;
49
0
  return 1;
50
0
}
51
52
int
53
1
debug_is_enabled(const char *name) {
54
1
  char *env = NULL;
55
1
  char *tmp = NULL;
56
1
  char *debugger = NULL;
57
1
  int enabled = 0;
58
59
  // get DEBUG env var
60
1
  if (!(env = getenv("DEBUG"))) return 0;
61
0
  if (!(tmp = strdup(env))) return 0;
62
63
0
  debugger = strtok(tmp, DELIMITER);
64
0
  while (debugger) {
65
    // support DEBUG=foo*
66
0
    if (1 == wildcardcmp(debugger, name)) {
67
0
      enabled = 1;
68
0
      break;
69
0
    }
70
0
    debugger = strtok(NULL, DELIMITER);
71
0
  }
72
73
0
  free(tmp);
74
0
  return enabled;
75
0
}
76
77
int
78
1
debug_init(debug_t *debugger, const char *name) {
79
  // seed, if necessary
80
1
  if (0 == seeded) {
81
1
    srand(clock());
82
1
    seeded = 1;
83
1
  }
84
85
  // random color
86
1
  debugger->color = 1 + (rand() % 6);
87
  // set enabled flag
88
1
  debugger->enabled = debug_is_enabled(name);
89
  // name, stream
90
1
  debugger->name = name;
91
1
  debugger->stream = stderr;
92
1
  return 0;
93
1
}
94
95
void
96
16
debug(debug_t *debugger, const char *fmt, ...) {
97
  // noop when disabled
98
16
  if (0 == debugger->enabled) return;
99
100
0
  char *pre = NULL;
101
0
  char *post = NULL;
102
0
  va_list args;
103
104
0
  va_start(args, fmt);
105
106
0
  if (use_colors(debugger->stream)) {
107
    // [color][name][/color]
108
0
    if (-1 == asprintf(&pre, FMT, debugger->color, debugger->name)) {
109
0
      va_end(args);
110
0
      return;
111
0
    }
112
0
  } else {
113
    // [name]
114
0
    if (!(pre = strdup(debugger->name))) {
115
0
      va_end(args);
116
0
      return;
117
0
    }
118
0
  }
119
120
  // format args
121
0
  if (-1 == vasprintf(&post, fmt, args)) {
122
0
    free(pre);
123
0
    va_end(args);
124
0
    return;
125
0
  }
126
127
  // print to stream
128
0
  fprintf(debugger->stream, " %s : %s\n", pre, post);
129
130
  // release memory
131
0
  free(pre);
132
0
  free(post);
133
0
}