xref: /linux-6.15/tools/lib/subcmd/subcmd-util.h (revision 4b6ab94e)
1*4b6ab94eSJosh Poimboeuf #ifndef __PERF_SUBCMD_UTIL_H
2*4b6ab94eSJosh Poimboeuf #define __PERF_SUBCMD_UTIL_H
3*4b6ab94eSJosh Poimboeuf 
4*4b6ab94eSJosh Poimboeuf #include <stdarg.h>
5*4b6ab94eSJosh Poimboeuf #include <stdlib.h>
6*4b6ab94eSJosh Poimboeuf #include <stdio.h>
7*4b6ab94eSJosh Poimboeuf 
8*4b6ab94eSJosh Poimboeuf #define NORETURN __attribute__((__noreturn__))
9*4b6ab94eSJosh Poimboeuf 
10*4b6ab94eSJosh Poimboeuf static inline void report(const char *prefix, const char *err, va_list params)
11*4b6ab94eSJosh Poimboeuf {
12*4b6ab94eSJosh Poimboeuf 	char msg[1024];
13*4b6ab94eSJosh Poimboeuf 	vsnprintf(msg, sizeof(msg), err, params);
14*4b6ab94eSJosh Poimboeuf 	fprintf(stderr, " %s%s\n", prefix, msg);
15*4b6ab94eSJosh Poimboeuf }
16*4b6ab94eSJosh Poimboeuf 
17*4b6ab94eSJosh Poimboeuf static NORETURN inline void die(const char *err, ...)
18*4b6ab94eSJosh Poimboeuf {
19*4b6ab94eSJosh Poimboeuf 	va_list params;
20*4b6ab94eSJosh Poimboeuf 
21*4b6ab94eSJosh Poimboeuf 	va_start(params, err);
22*4b6ab94eSJosh Poimboeuf 	report(" Fatal: ", err, params);
23*4b6ab94eSJosh Poimboeuf 	exit(128);
24*4b6ab94eSJosh Poimboeuf 	va_end(params);
25*4b6ab94eSJosh Poimboeuf }
26*4b6ab94eSJosh Poimboeuf 
27*4b6ab94eSJosh Poimboeuf #define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
28*4b6ab94eSJosh Poimboeuf 
29*4b6ab94eSJosh Poimboeuf #define alloc_nr(x) (((x)+16)*3/2)
30*4b6ab94eSJosh Poimboeuf 
31*4b6ab94eSJosh Poimboeuf /*
32*4b6ab94eSJosh Poimboeuf  * Realloc the buffer pointed at by variable 'x' so that it can hold
33*4b6ab94eSJosh Poimboeuf  * at least 'nr' entries; the number of entries currently allocated
34*4b6ab94eSJosh Poimboeuf  * is 'alloc', using the standard growing factor alloc_nr() macro.
35*4b6ab94eSJosh Poimboeuf  *
36*4b6ab94eSJosh Poimboeuf  * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
37*4b6ab94eSJosh Poimboeuf  */
38*4b6ab94eSJosh Poimboeuf #define ALLOC_GROW(x, nr, alloc) \
39*4b6ab94eSJosh Poimboeuf 	do { \
40*4b6ab94eSJosh Poimboeuf 		if ((nr) > alloc) { \
41*4b6ab94eSJosh Poimboeuf 			if (alloc_nr(alloc) < (nr)) \
42*4b6ab94eSJosh Poimboeuf 				alloc = (nr); \
43*4b6ab94eSJosh Poimboeuf 			else \
44*4b6ab94eSJosh Poimboeuf 				alloc = alloc_nr(alloc); \
45*4b6ab94eSJosh Poimboeuf 			x = xrealloc((x), alloc * sizeof(*(x))); \
46*4b6ab94eSJosh Poimboeuf 		} \
47*4b6ab94eSJosh Poimboeuf 	} while(0)
48*4b6ab94eSJosh Poimboeuf 
49*4b6ab94eSJosh Poimboeuf static inline void *xrealloc(void *ptr, size_t size)
50*4b6ab94eSJosh Poimboeuf {
51*4b6ab94eSJosh Poimboeuf 	void *ret = realloc(ptr, size);
52*4b6ab94eSJosh Poimboeuf 	if (!ret && !size)
53*4b6ab94eSJosh Poimboeuf 		ret = realloc(ptr, 1);
54*4b6ab94eSJosh Poimboeuf 	if (!ret) {
55*4b6ab94eSJosh Poimboeuf 		ret = realloc(ptr, size);
56*4b6ab94eSJosh Poimboeuf 		if (!ret && !size)
57*4b6ab94eSJosh Poimboeuf 			ret = realloc(ptr, 1);
58*4b6ab94eSJosh Poimboeuf 		if (!ret)
59*4b6ab94eSJosh Poimboeuf 			die("Out of memory, realloc failed");
60*4b6ab94eSJosh Poimboeuf 	}
61*4b6ab94eSJosh Poimboeuf 	return ret;
62*4b6ab94eSJosh Poimboeuf }
63*4b6ab94eSJosh Poimboeuf 
64*4b6ab94eSJosh Poimboeuf #define astrcatf(out, fmt, ...)						\
65*4b6ab94eSJosh Poimboeuf ({									\
66*4b6ab94eSJosh Poimboeuf 	char *tmp = *(out);						\
67*4b6ab94eSJosh Poimboeuf 	if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1)	\
68*4b6ab94eSJosh Poimboeuf 		die("asprintf failed");					\
69*4b6ab94eSJosh Poimboeuf 	free(tmp);							\
70*4b6ab94eSJosh Poimboeuf })
71*4b6ab94eSJosh Poimboeuf 
72*4b6ab94eSJosh Poimboeuf static inline void astrcat(char **out, const char *add)
73*4b6ab94eSJosh Poimboeuf {
74*4b6ab94eSJosh Poimboeuf 	char *tmp = *out;
75*4b6ab94eSJosh Poimboeuf 
76*4b6ab94eSJosh Poimboeuf 	if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
77*4b6ab94eSJosh Poimboeuf 		die("asprintf failed");
78*4b6ab94eSJosh Poimboeuf 
79*4b6ab94eSJosh Poimboeuf 	free(tmp);
80*4b6ab94eSJosh Poimboeuf }
81*4b6ab94eSJosh Poimboeuf 
82*4b6ab94eSJosh Poimboeuf static inline int prefixcmp(const char *str, const char *prefix)
83*4b6ab94eSJosh Poimboeuf {
84*4b6ab94eSJosh Poimboeuf 	for (; ; str++, prefix++)
85*4b6ab94eSJosh Poimboeuf 		if (!*prefix)
86*4b6ab94eSJosh Poimboeuf 			return 0;
87*4b6ab94eSJosh Poimboeuf 		else if (*str != *prefix)
88*4b6ab94eSJosh Poimboeuf 			return (unsigned char)*prefix - (unsigned char)*str;
89*4b6ab94eSJosh Poimboeuf }
90*4b6ab94eSJosh Poimboeuf 
91*4b6ab94eSJosh Poimboeuf #endif /* __PERF_SUBCMD_UTIL_H */
92