xref: /linux-6.15/tools/lib/subcmd/subcmd-util.h (revision b2441318)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21843b4e0SJosh Poimboeuf #ifndef __SUBCMD_UTIL_H
31843b4e0SJosh Poimboeuf #define __SUBCMD_UTIL_H
44b6ab94eSJosh Poimboeuf 
54b6ab94eSJosh Poimboeuf #include <stdarg.h>
64b6ab94eSJosh Poimboeuf #include <stdlib.h>
74b6ab94eSJosh Poimboeuf #include <stdio.h>
84b6ab94eSJosh Poimboeuf 
94b6ab94eSJosh Poimboeuf #define NORETURN __attribute__((__noreturn__))
104b6ab94eSJosh Poimboeuf 
114b6ab94eSJosh Poimboeuf static inline void report(const char *prefix, const char *err, va_list params)
124b6ab94eSJosh Poimboeuf {
134b6ab94eSJosh Poimboeuf 	char msg[1024];
144b6ab94eSJosh Poimboeuf 	vsnprintf(msg, sizeof(msg), err, params);
154b6ab94eSJosh Poimboeuf 	fprintf(stderr, " %s%s\n", prefix, msg);
164b6ab94eSJosh Poimboeuf }
174b6ab94eSJosh Poimboeuf 
184b6ab94eSJosh Poimboeuf static NORETURN inline void die(const char *err, ...)
194b6ab94eSJosh Poimboeuf {
204b6ab94eSJosh Poimboeuf 	va_list params;
214b6ab94eSJosh Poimboeuf 
224b6ab94eSJosh Poimboeuf 	va_start(params, err);
234b6ab94eSJosh Poimboeuf 	report(" Fatal: ", err, params);
244b6ab94eSJosh Poimboeuf 	exit(128);
254b6ab94eSJosh Poimboeuf 	va_end(params);
264b6ab94eSJosh Poimboeuf }
274b6ab94eSJosh Poimboeuf 
284b6ab94eSJosh Poimboeuf #define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
294b6ab94eSJosh Poimboeuf 
304b6ab94eSJosh Poimboeuf #define alloc_nr(x) (((x)+16)*3/2)
314b6ab94eSJosh Poimboeuf 
324b6ab94eSJosh Poimboeuf /*
334b6ab94eSJosh Poimboeuf  * Realloc the buffer pointed at by variable 'x' so that it can hold
344b6ab94eSJosh Poimboeuf  * at least 'nr' entries; the number of entries currently allocated
354b6ab94eSJosh Poimboeuf  * is 'alloc', using the standard growing factor alloc_nr() macro.
364b6ab94eSJosh Poimboeuf  *
374b6ab94eSJosh Poimboeuf  * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
384b6ab94eSJosh Poimboeuf  */
394b6ab94eSJosh Poimboeuf #define ALLOC_GROW(x, nr, alloc) \
404b6ab94eSJosh Poimboeuf 	do { \
414b6ab94eSJosh Poimboeuf 		if ((nr) > alloc) { \
424b6ab94eSJosh Poimboeuf 			if (alloc_nr(alloc) < (nr)) \
434b6ab94eSJosh Poimboeuf 				alloc = (nr); \
444b6ab94eSJosh Poimboeuf 			else \
454b6ab94eSJosh Poimboeuf 				alloc = alloc_nr(alloc); \
464b6ab94eSJosh Poimboeuf 			x = xrealloc((x), alloc * sizeof(*(x))); \
474b6ab94eSJosh Poimboeuf 		} \
484b6ab94eSJosh Poimboeuf 	} while(0)
494b6ab94eSJosh Poimboeuf 
504b6ab94eSJosh Poimboeuf static inline void *xrealloc(void *ptr, size_t size)
514b6ab94eSJosh Poimboeuf {
524b6ab94eSJosh Poimboeuf 	void *ret = realloc(ptr, size);
534b6ab94eSJosh Poimboeuf 	if (!ret && !size)
544b6ab94eSJosh Poimboeuf 		ret = realloc(ptr, 1);
554b6ab94eSJosh Poimboeuf 	if (!ret) {
564b6ab94eSJosh Poimboeuf 		ret = realloc(ptr, size);
574b6ab94eSJosh Poimboeuf 		if (!ret && !size)
584b6ab94eSJosh Poimboeuf 			ret = realloc(ptr, 1);
594b6ab94eSJosh Poimboeuf 		if (!ret)
604b6ab94eSJosh Poimboeuf 			die("Out of memory, realloc failed");
614b6ab94eSJosh Poimboeuf 	}
624b6ab94eSJosh Poimboeuf 	return ret;
634b6ab94eSJosh Poimboeuf }
644b6ab94eSJosh Poimboeuf 
654b6ab94eSJosh Poimboeuf #define astrcatf(out, fmt, ...)						\
664b6ab94eSJosh Poimboeuf ({									\
674b6ab94eSJosh Poimboeuf 	char *tmp = *(out);						\
684b6ab94eSJosh Poimboeuf 	if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1)	\
694b6ab94eSJosh Poimboeuf 		die("asprintf failed");					\
704b6ab94eSJosh Poimboeuf 	free(tmp);							\
714b6ab94eSJosh Poimboeuf })
724b6ab94eSJosh Poimboeuf 
734b6ab94eSJosh Poimboeuf static inline void astrcat(char **out, const char *add)
744b6ab94eSJosh Poimboeuf {
754b6ab94eSJosh Poimboeuf 	char *tmp = *out;
764b6ab94eSJosh Poimboeuf 
774b6ab94eSJosh Poimboeuf 	if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
784b6ab94eSJosh Poimboeuf 		die("asprintf failed");
794b6ab94eSJosh Poimboeuf 
804b6ab94eSJosh Poimboeuf 	free(tmp);
814b6ab94eSJosh Poimboeuf }
824b6ab94eSJosh Poimboeuf 
831843b4e0SJosh Poimboeuf #endif /* __SUBCMD_UTIL_H */
84