Skip to content

Commit f112e7b

Browse files
committed
c_gen: use raw strings for trace code
1 parent ce226cb commit f112e7b

File tree

1 file changed

+170
-164
lines changed

1 file changed

+170
-164
lines changed

generator/c/c_generator_trace.c2

Lines changed: 170 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -176,183 +176,189 @@ fn void Generator.writeCalls(Generator* gen, string_buffer.Buf* out) {
176176
}
177177
out.add("};\n\n");
178178

179-
const char[] begin =
180-
```c
181-
struct c2_func_t {
182-
unsigned count;
183-
unsigned short filename_idx;
184-
unsigned short line;
185-
const char *funcname;
186-
};
187-
static struct c2_func_t c2_func_data[] = {
188-
```;
189-
out.add(begin);
179+
out.add(
180+
```c
181+
struct c2_func_t {
182+
unsigned count;
183+
unsigned short filename_idx;
184+
unsigned short line;
185+
const char *funcname;
186+
};
187+
static struct c2_func_t c2_func_data[] = {
188+
```);
190189
// TODO: store function definition location
191190
n = gen.funcnames.length();
192191
for (u32 i = 0; i < n; i++) {
193192
out.print(" { 0, 0, 0, \"%s\" },\n", gen.funcnames.get(i));
194193
}
195-
out.add("};\n\n");
194+
out.add(
195+
```c
196+
};
196197

197-
out.add("struct c2_trace_t {\n"
198-
" unsigned count;\n"
199-
" unsigned char filename_idx;\n"
200-
" unsigned char column;\n"
201-
" unsigned short line;\n"
202-
" unsigned short caller_idx;\n"
203-
" unsigned short callee_idx;\n"
204-
"};\n"
205-
"static struct c2_trace_t c2_trace_data[] = {\n"
206-
);
198+
struct c2_trace_t {
199+
unsigned count;
200+
unsigned char filename_idx;
201+
unsigned char column;
202+
unsigned short line;
203+
unsigned short caller_idx;
204+
unsigned short callee_idx;
205+
};
206+
static struct c2_trace_t c2_trace_data[] = {
207+
```);
207208
for (u32 i = 0; i < gen.calls.count; i++) {
208209
out.print(" { 0, %d, %d, %d, %d, %d },\n",
209210
gen.calls.array[i].filename_idx, gen.calls.array[i].column, gen.calls.array[i].line,
210211
gen.calls.array[i].caller_idx, gen.calls.array[i].callee_idx);
211212
}
212-
out.add("};\n\n");
213213

214-
out.add("static const unsigned c2_trace_length = sizeof(c2_trace_data) / sizeof(c2_trace_data[0]);\n"
215-
"unsigned c2_trace_counts[sizeof(c2_trace_data) / sizeof(c2_trace_data[0])];\n\n"
216-
);
217-
out.add("char *getenv(const char *);\n"
218-
"int dprintf(int fd, const char *format, ...);\n"
219-
"int strcmp(const char *s1, const char *s2);\n"
220-
"typedef unsigned long size_t;\n"
221-
"void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));\n"
222-
"int sscanf(const char *, const char *, ...);\n\n"
223-
);
224-
out.add("static int c2_match_name(const char *name, const char *pattern) {\n"
225-
" for (;;) {\n"
226-
" char c1, c2;\n"
227-
" while ((c1 = *name++) == (c2 = *pattern++)) {\n"
228-
" if (!c1) return 1;\n"
229-
" }\n"
230-
" if (c2 == '?') {\n"
231-
" if (c1) continue;\n"
232-
" return 0;\n"
233-
" }\n"
234-
" if (c2 == '*') {\n"
235-
" c2 = *pattern++;\n"
236-
" if (!c2 || c2 == ',' || c2 == ';') return 1;\n"
237-
" for (; c1; c1 = *name++) {\n"
238-
" if (c1 == c2 && c2_match_name(name, pattern)) return 1;\n"
239-
" }\n"
240-
" return 0;\n"
241-
" }\n"
242-
" return (!c1 && (c2 == ',' || c2 == ';'));\n"
243-
" }\n"
244-
"}\n\n"
245-
);
246-
out.add("static int c2_match_pattern(const char *name, const char *pattern) {\n"
247-
" if (!pattern || !*pattern) return 1;\n"
248-
" for (const char *p = pattern; *p;) {\n"
249-
" if (c2_match_name(name, p)) return 1;\n"
250-
" char c;\n"
251-
" while ((c = *p++) != 0 && c != ',' && c != ';') continue;\n"
252-
" if (c != ',') break;\n"
253-
" }\n"
254-
" return 0;\n"
255-
"}\n\n"
256-
);
257-
out.add("static int c2_cmp_funcs(const void *a, const void *b) {\n"
258-
" const struct c2_trace_t *aa = a;\n"
259-
" const struct c2_trace_t *bb = b;\n"
260-
" struct c2_func_t *fa = &c2_func_data[aa->callee_idx];\n"
261-
" struct c2_func_t *fb = &c2_func_data[bb->callee_idx];\n"
262-
" if (fa->count != fb->count) return fa->count < fb->count ? 1 : -1;\n"
263-
" if (fa != fb) return strcmp(fa->funcname, fb->funcname);\n"
264-
" return (aa->count < bb->count) - (aa->count > bb->count);\n"
265-
"}\n\n"
266-
);
267-
out.add("static int c2_cmp_calls(const void *a, const void *b) {\n"
268-
" const struct c2_trace_t *aa = a;\n"
269-
" const struct c2_trace_t *bb = b;\n"
270-
" return (aa->count < bb->count) - (aa->count > bb->count);\n"
271-
"}\n\n"
272-
);
273-
out.add("void __attribute__((destructor)) c2_trace_calls(void) {\n"
274-
" const char *p = getenv(\"C2_TRACE\");\n"
275-
" const char *pattern = 0;\n"
276-
" const char *filename = 0;\n"
277-
" const char *caller = 0;\n"
278-
" if (!p || !*p) return;\n"
279-
" unsigned min = 1, min2 = 1;\n"
280-
" int pos = 0, mode = 3, fd = 1, indent = 2;\n"
281-
" for (; *p; p += pos) {\n"
282-
" for (pos = 0;;) {\n"
283-
" sscanf(p, \" min%*1[=]%n%u\", &pos, &min);\n"
284-
" if (pos) break;\n"
285-
" sscanf(p, \" min2%*1[=]%n%u\", &pos, &min2);\n"
286-
" if (pos) break;\n"
287-
" sscanf(p, \" indent%*1[=]%n%u\", &pos, &indent);\n"
288-
" if (pos) break;\n"
289-
" sscanf(p, \" mode%*1[=]%n%d\", &pos, &mode);\n"
290-
" if (pos) break;\n"
291-
" sscanf(p, \" fd%*1[=]%n%d\", &pos, &fd);\n"
292-
" if (pos) break;\n"
293-
" sscanf(p, \" name%*1[=]%n\", &pos);\n"
294-
" if (pos) { pattern = p + pos; break; }\n"
295-
" sscanf(p, \" filename%*1[=]%n\", &pos);\n"
296-
" if (pos) { filename = p + pos; break; }\n"
297-
" sscanf(p, \" caller%*1[=]%n\", &pos);\n"
298-
" if (pos) { caller = p + pos; break; }\n"
299-
" sscanf(p, \"%*[^;=]%*1[=]%n%\", &pos);\n"
300-
" break;\n"
301-
" }\n"
302-
" if (!pos) pattern = p;\n"
303-
" while (p[pos] && p[pos++] != ';') continue;\n"
304-
" }\n"
305-
" if (!mode) return;\n"
306-
" unsigned *counts = c2_trace_counts;\n"
307-
" struct c2_trace_t* data = c2_trace_data;\n"
308-
" unsigned n = c2_trace_length;\n"
309-
" for (unsigned i = 0; i < n; i++) {\n"
310-
" struct c2_trace_t *cp = &data[i];\n"
311-
" if (c2_match_pattern(c2_func_data[cp->callee_idx].funcname, pattern)\n"
312-
" && c2_match_pattern(c2_filenames[cp->filename_idx], filename)\n"
313-
" && c2_match_pattern(c2_func_data[cp->caller_idx].funcname, caller)) {\n"
314-
" cp->count = counts[i];\n"
315-
" c2_func_data[cp->callee_idx].count += counts[i];\n"
316-
" }\n"
317-
" }\n"
318-
" if (mode == 2) {\n"
319-
" qsort(data, n, sizeof(*data), c2_cmp_calls);\n"
320-
" indent = 0;\n"
321-
" min2 = min;\n"
322-
" } else {\n"
323-
" qsort(data, n, sizeof(*data), c2_cmp_funcs);\n"
324-
" }\n"
325-
" struct c2_func_t *last = 0;\n"
326-
" int show = 0;\n"
327-
" for (unsigned i = 0; i < n; i++) {\n"
328-
" struct c2_trace_t *cp = &data[i];\n"
329-
" struct c2_func_t *func = &c2_func_data[cp->callee_idx];\n"
330-
" unsigned count1 = func->count;\n"
331-
" unsigned count2 = cp->count;\n"
332-
" if (count1 < min) continue;\n"
333-
" if (func != last) {\n"
334-
" show = mode & 2;\n"
335-
" if (mode & 1) {\n"
336-
" dprintf(fd, \"%.*s%s: %u call%.*s\\n\", show, \"\\n\",\n"
337-
" func->funcname, count1, count1 != 1, \"s\");\n"
338-
" }\n"
339-
" last = func;\n"
340-
" }\n"
341-
" if (show && count2 >= min2) {\n"
342-
" dprintf(fd, \"%*s%s:%d:%d: %s: %u call%.*s from %s\\n\",\n"
343-
" indent, \"\",\n"
344-
" c2_filenames[cp->filename_idx], cp->line, cp->column,\n"
345-
" func->funcname, count2, count2 != 1, \"s\",\n"
346-
" c2_func_data[cp->caller_idx].funcname);\n"
347-
" }\n"
348-
" }\n"
349-
"}\n"
350-
);
214+
out.add(
215+
```c
216+
};
217+
218+
static const unsigned c2_trace_length = sizeof(c2_trace_data) / sizeof(c2_trace_data[0]);
219+
unsigned c2_trace_counts[sizeof(c2_trace_data) / sizeof(c2_trace_data[0])];
220+
221+
char *getenv(const char *);
222+
int dprintf(int fd, const char *format, ...);
223+
int strcmp(const char *s1, const char *s2);
224+
typedef unsigned long size_t;
225+
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
226+
int sscanf(const char *, const char *, ...);
227+
228+
static int c2_match_name(const char *name, const char *pattern) {
229+
for (;;) {
230+
char c1, c2;
231+
while ((c1 = *name++) == (c2 = *pattern++)) {
232+
if (!c1) return 1;
233+
}
234+
if (c2 == '?') {
235+
if (c1) continue;
236+
return 0;
237+
}
238+
if (c2 == '*') {
239+
c2 = *pattern++;
240+
if (!c2 || c2 == ',' || c2 == ';') return 1;
241+
for (; c1; c1 = *name++) {
242+
if (c1 == c2 && c2_match_name(name, pattern)) return 1;
243+
}
244+
return 0;
245+
}
246+
return (!c1 && (c2 == ',' || c2 == ';'));
247+
}
248+
}
249+
250+
static int c2_match_pattern(const char *name, const char *pattern) {
251+
if (!pattern || !*pattern) return 1;
252+
for (const char *p = pattern; *p;) {
253+
if (c2_match_name(name, p)) return 1;
254+
char c;
255+
while ((c = *p++) != 0 && c != ',' && c != ';') continue;
256+
if (c != ',') break;
257+
}
258+
return 0;
259+
}
260+
261+
static int c2_cmp_funcs(const void *a, const void *b) {
262+
const struct c2_trace_t *aa = a;
263+
const struct c2_trace_t *bb = b;
264+
struct c2_func_t *fa = &c2_func_data[aa->callee_idx];
265+
struct c2_func_t *fb = &c2_func_data[bb->callee_idx];
266+
if (fa->count != fb->count) return fa->count < fb->count ? 1 : -1;
267+
if (fa != fb) return strcmp(fa->funcname, fb->funcname);
268+
return (aa->count < bb->count) - (aa->count > bb->count);
269+
}
270+
271+
static int c2_cmp_calls(const void *a, const void *b) {
272+
const struct c2_trace_t *aa = a;
273+
const struct c2_trace_t *bb = b;
274+
return (aa->count < bb->count) - (aa->count > bb->count);
275+
}
276+
277+
void __attribute__((destructor)) c2_trace_calls(void) {
278+
const char *p = getenv("C2_TRACE");
279+
const char *pattern = 0;
280+
const char *filename = 0;
281+
const char *caller = 0;
282+
if (!p || !*p) return;
283+
unsigned min = 1, min2 = 1;
284+
int pos = 0, mode = 3, fd = 1, indent = 2;
285+
for (; *p; p += pos) {
286+
for (pos = 0;;) {
287+
sscanf(p, " min%*1[=]%n%u", &pos, &min);
288+
if (pos) break;
289+
sscanf(p, " min2%*1[=]%n%u", &pos, &min2);
290+
if (pos) break;
291+
sscanf(p, " indent%*1[=]%n%u", &pos, &indent);
292+
if (pos) break;
293+
sscanf(p, " mode%*1[=]%n%d", &pos, &mode);
294+
if (pos) break;
295+
sscanf(p, " fd%*1[=]%n%d", &pos, &fd);
296+
if (pos) break;
297+
sscanf(p, " name%*1[=]%n", &pos);
298+
if (pos) { pattern = p + pos; break; }
299+
sscanf(p, " filename%*1[=]%n", &pos);
300+
if (pos) { filename = p + pos; break; }
301+
sscanf(p, " caller%*1[=]%n", &pos);
302+
if (pos) { caller = p + pos; break; }
303+
sscanf(p, "%*[^;=]%*1[=]%n%", &pos);
304+
break;
305+
}
306+
if (!pos) pattern = p;
307+
while (p[pos] && p[pos++] != ';') continue;
308+
}
309+
if (!mode) return;
310+
unsigned *counts = c2_trace_counts;
311+
struct c2_trace_t* data = c2_trace_data;
312+
unsigned n = c2_trace_length;
313+
for (unsigned i = 0; i < n; i++) {
314+
struct c2_trace_t *cp = &data[i];
315+
if (c2_match_pattern(c2_func_data[cp->callee_idx].funcname, pattern)
316+
&& c2_match_pattern(c2_filenames[cp->filename_idx], filename)
317+
&& c2_match_pattern(c2_func_data[cp->caller_idx].funcname, caller)) {
318+
cp->count = counts[i];
319+
c2_func_data[cp->callee_idx].count += counts[i];
320+
}
321+
}
322+
if (mode == 2) {
323+
qsort(data, n, sizeof(*data), c2_cmp_calls);
324+
indent = 0;
325+
min2 = min;
326+
} else {
327+
qsort(data, n, sizeof(*data), c2_cmp_funcs);
328+
}
329+
struct c2_func_t *last = 0;
330+
int show = 0;
331+
for (unsigned i = 0; i < n; i++) {
332+
struct c2_trace_t *cp = &data[i];
333+
struct c2_func_t *func = &c2_func_data[cp->callee_idx];
334+
unsigned count1 = func->count;
335+
unsigned count2 = cp->count;
336+
if (count1 < min) continue;
337+
if (func != last) {
338+
show = mode & 2;
339+
if (mode & 1) {
340+
dprintf(fd, "%.*s%s: %u call%.*s\n", show, "\n",
341+
func->funcname, count1, count1 != 1, "s");
342+
}
343+
last = func;
344+
}
345+
if (show && count2 >= min2) {
346+
dprintf(fd, "%*s%s:%d:%d: %s: %u call%.*s from %s\n",
347+
indent, "",
348+
c2_filenames[cp->filename_idx], cp->line, cp->column,
349+
func->funcname, count2, count2 != 1, "s",
350+
c2_func_data[cp->caller_idx].funcname);
351+
}
352+
}
353+
}
354+
```);
351355
}
352356

353357
fn void Generator.writeCallExterns(Generator* gen, string_buffer.Buf* out) {
354-
out.add("extern unsigned c2_trace_counts[];\n"
355-
"extern void c2_trace_calls(void);\n"
356-
"extern int atexit(void (*func)(void));\n"
357-
);
358+
out.add(
359+
```c
360+
extern unsigned c2_trace_counts[];
361+
extern void c2_trace_calls(void);
362+
extern int atexit(void (*func)(void));
363+
```);
358364
}

0 commit comments

Comments
 (0)