main shrubtools / proto / util.c
  1#include <errno.h>
  2#include <stdarg.h>
  3#include <stdbool.h>
  4#include <stdint.h>
  5#include <stdio.h>
  6#include <stdlib.h>
  7#include <string.h>
  8
  9#include "util.h"
 10
 11extern const char *argv0;
 12
 13static void
 14vwarn(const char *fmt, va_list ap)
 15{
 16	fprintf(stderr, "%s: ", argv0);
 17	vfprintf(stderr, fmt, ap);
 18	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
 19		putc(' ', stderr);
 20		perror(NULL);
 21	} else {
 22		putc('\n', stderr);
 23	}
 24}
 25
 26void
 27warn(const char *fmt, ...)
 28{
 29	va_list ap;
 30
 31	va_start(ap, fmt);
 32	vwarn(fmt, ap);
 33	va_end(ap);
 34}
 35
 36void
 37die(const char *fmt, ...)
 38{
 39	va_list ap;
 40
 41	va_start(ap, fmt);
 42	vwarn(fmt, ap);
 43	va_end(ap);
 44	exit(1);
 45}
 46
 47void *
 48xmalloc(size_t n)
 49{
 50	void *p;
 51
 52	p = malloc(n ? n : 1);
 53	if (!p)
 54		die("malloc:");
 55	return p;
 56}
 57
 58void *
 59xcalloc(size_t n, size_t m)
 60{
 61	void *p;
 62
 63	p = calloc(n, m);
 64	if (!p)
 65		die("calloc:");
 66	return p;
 67}
 68
 69static void *
 70reallocarray_(void *p, size_t n, size_t m)
 71{
 72	if (m && n > SIZE_MAX / m) {
 73		errno = ENOMEM;
 74		return NULL;
 75	}
 76	return realloc(p, n * m);
 77}
 78
 79void *
 80xreallocarray(void *p, size_t n, size_t m)
 81{
 82	p = reallocarray_(p, n, m);
 83	if (!p)
 84		die("reallocarray:");
 85	return p;
 86}
 87
 88char *
 89xstrdup(const char *s)
 90{
 91	size_t n;
 92	char *p;
 93
 94	n = strlen(s) + 1;
 95	p = xmalloc(n);
 96	memcpy(p, s, n);
 97	return p;
 98}
 99
100char *
101xmemdup0(const char *s, size_t n)
102{
103	char *p;
104
105	p = xmalloc(n + 1);
106	memcpy(p, s, n);
107	p[n] = '\0';
108	return p;
109}
110
111int
112xasprintf(char **s, const char *fmt, ...)
113{
114	va_list ap;
115	int ret;
116	size_t n;
117
118	va_start(ap, fmt);
119	ret = vsnprintf(NULL, 0, fmt, ap);
120	va_end(ap);
121	if (ret < 0)
122		die("vsnprintf:");
123	n = (size_t)ret + 1;
124	*s = xmalloc(n);
125	va_start(ap, fmt);
126	ret = vsnprintf(*s, n, fmt, ap);
127	va_end(ap);
128	if (ret < 0 || (size_t)ret >= n)
129		die("vsnprintf:");
130	return ret;
131}