-
Notifications
You must be signed in to change notification settings - Fork 1
/
example.c
160 lines (131 loc) · 4.59 KB
/
example.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* Step 1. Configure (optional) */
#define PK_TAG "PK-EXAMPLE"
#define PK_DUMP_WIDTH 16
/* Step 2. Include pk.h */
#include "pk.h"
/* unistd.h for sleeping */
#include <unistd.h>
struct foo {
int bar;
char *baz;
};
int test_fn(void) { return 42; }
int main(int argc, char *argv[]) {
int i, o, ret;
char s[] = " test string with some whitespace ";
struct foo foo_instance;
struct timespec t, a;
/* Step 3. Use it!
* All output will include the PK_TAG, the file, line number, and function
* name
*/
/* --- generic messages */
/* PK() and PKS() are simple... a bare message, and a message with a static
* string. Note that the string passed to PKS() is not a format string,
* while the string passed to PKF() _is_ a format string, and thus care
* needs to be taken to escape format specifiers
*/
PK();
PKS("test message");
i = 42;
/* PKF() behaves just like printf() / printk() ... you can pass a format
* paired with variadic arguments. Note that the first string passed to
* PKF() is a format string, and thus care needs to be taken to escape
* format specifiers
*/
PKF("I'm about to talk about 'i'");
PKF("'i' has the value %d", i);
/* PKV() will print the variable's name and value. You can use square
* brackets in the format string for values that may have whitespace
*/
PKV("%d", i);
PKV("[%s]", s);
/* PKV() may also be used to print multiple name / value pairs
*/
PKV("%d", i, "[%s]", s);
/* PKVS() allows easy access to multiple struct members at once
*/
memset(&foo_instance, 0, sizeof(foo_instance));
foo_instance.bar = 1234;
foo_instance.baz = " hello there ";
PKVS(foo_instance,
"%d", bar,
"[%s]", baz
);
/* PKE() will output the value of errno, and the relevant descripive string
*/
errno = EINVAL;
PKE("uhoh");
PKE("uhoh, myfunc() failed %d times", 3);
/* PKR() will output the function and its return value, and may be used in
* assignments
*/
ret = PKR(int, "%d", test_fn());
ret = PKRIF(int, "%d", == 42, test_fn()); /* condition is met, output */
ret = PKRIF(int, "%d", < 42, test_fn()); /* condition is not met, no output */
/* --- time-based messages --- */
/* PKTSTART() permits you to get the current time... effectively starting a
* timer. It doesn't produce any output
*/
PKTSTART(t);
/* PKTSTAMP() permits a simple timestamp, with format string and arguments.
* The output is the Unix timestamp specified to nano seconds, but this may
* not be attainable on your system.
*/
PKTSTAMP("the answer is %d", i);
/* PKTDIFF() outputs the difference in time between "now" and the reference
* timestamp
*/
PKTDIFF(t, "that was fast!");
/* PKTACC() permits accumulation of time in a given variable. For example
* you may want to profile a certain portion of a loop, but not the entire
* loop. _PKTACC() may be used if you wish to accumulate without producing
* output
*/
memset(&a, 0, sizeof(a));
for(o = 0; o < 5; o++) {
/* this sleep is not counted */
usleep(10000);
PKTSTART(t);
/* but this sleep is */
usleep(1000);
PKTACC(t, a, "iteration %d", o);
}
/* PKTRATE() permits automatic calculation of the frequency (n/t)
*/
PKTSTART(t);
usleep(10000);
PKTRATE(t, 10, "we waited for ~10ms for 10 items... which is ~1ms each, or 1 kHz!");
/* PKTRAW(), PKTRAWS(), and PKTRAWF() permit printing a raw timestamp,
* perhaps as acquired by other means. These functinos are equivelant to
* PK(), PKS() and PKF() respectively. The same note applies re: care with
* format specifiers
*/
clock_gettime(CLOCK_REALTIME, &t);
PKTRAW(t);
PKTRAWS(t, "static message");
PKTRAWF(t, "format string %d", i);
/* --- hex-dump messages --- */
/* PKDUMP() will produce a nice looking hex-dump. The dump's width can be
* adjusted by defining PK_DUMP_WIDTH to a value of your choosing. The
* pointer and length will be displayed above the dump. A NULL or length
* of zero still produce output. The dump can be gathered by the begin and
* end cut-marks, as well as the fact that all output has the same line
* number
*/
PKDUMP(NULL, 0, "this has no data or length");
PKDUMP(s, sizeof(s), "this is our friendly string");
/* PKBSTR() will produce the data as text, with non-printcharacters escaped
* as hex sequences "\x??"
*/
PKBSTR("hello", 5);
PKBSTR("hello\tthere", 11);
/* PKPSTR() will produce the data as text, with non-printcharacters rendered
* as '.'
*/
PKPSTR("hello", 5);
PKPSTR("hello\tthere", 11);
/* PKLINES() will produce a nice looking multi-line block of text, and
* shares many characteristics with PKDUMP() */
PKLINES("test block\n\nof\ntext", 128, "this is a multi-line string");
}