]> git.tuebingen.mpg.de Git - tfortune.git/blob - util.c
initial
[tfortune.git] / util.c
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #include "tf.h"
4
5 DEFINE_TF_ERRLIST;
6
7 int atoi64(const char *str, int64_t *value)
8 {
9         char *endptr;
10         long long tmp;
11
12         errno = 0; /* To distinguish success/failure after call */
13         tmp = strtoll(str, &endptr, 10);
14         if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN))
15                 return -E_ATOI_OVERFLOW;
16         /*
17          * If there were no digits at all, strtoll() stores the original value
18          * of str in *endptr.
19          */
20         if (endptr == str)
21                 return -E_ATOI_NO_DIGITS;
22         /*
23          * The implementation may also set errno and return 0 in case no
24          * conversion was performed.
25          */
26         if (errno != 0 && tmp == 0)
27                 return -E_ATOI_NO_DIGITS;
28         if (*endptr != '\0') /* Further characters after number */
29                 return -E_ATOI_JUNK_AT_END;
30         *value = tmp;
31         return 1;
32 }
33
34 __attribute__ ((warn_unused_result))
35 void *xrealloc(void *p, size_t size)
36 {
37         /*
38          * No need to check for NULL pointers: If p is NULL, the call
39          * to realloc is equivalent to malloc(size)
40          */
41         assert(size);
42         if (!(p = realloc(p, size))) {
43                 EMERG_LOG("realloc failed (size = %zu), aborting\n", size);
44                 exit(EXIT_FAILURE);
45         }
46         return p;
47 }
48
49 __attribute__ ((warn_unused_result))
50 void *xmalloc(size_t size)
51 {
52         return xrealloc(NULL, size);
53 }
54
55 __attribute__ ((warn_unused_result))
56 void *xcalloc(size_t size)
57 {
58         void *p = xmalloc(size);
59         memset(p, 0, size);
60         return p;
61 }
62
63 /*
64  * Print a formated message to a dynamically allocated string.
65  *
66  * This function is similar to vasprintf(), a GNU extension which is not in C
67  * or POSIX. It allocates a string large enough to hold the output including
68  * the terminating null byte. The allocated string is returned via the first
69  * argument and must be freed by the caller. However, unlike vasprintf(), this
70  * function calls exit() if insufficient memory is available, while vasprintf()
71  * returns -1 in this case.
72  *
73  * It returns the number of bytes written, not including the terminating \p
74  * NULL character.
75  */
76 __attribute__ ((format (printf, 2, 0)))
77 unsigned xvasprintf(char **result, const char *fmt, va_list ap)
78 {
79         int ret;
80         size_t size = 150;
81         va_list aq;
82
83         *result = xmalloc(size + 1);
84         va_copy(aq, ap);
85         ret = vsnprintf(*result, size, fmt, aq);
86         va_end(aq);
87         assert(ret >= 0);
88         if ((size_t)ret < size)
89                 return ret;
90         size = ret + 1;
91         *result = xrealloc(*result, size);
92         va_copy(aq, ap);
93         ret = vsnprintf(*result, size, fmt, aq);
94         va_end(aq);
95         assert(ret >= 0 && (size_t)ret < size);
96         return ret;
97 }
98
99 __attribute__ ((format (printf, 2, 3)))
100 /* Print to a dynamically allocated string, variable number of arguments.  */
101 unsigned xasprintf(char **result, const char *fmt, ...)
102 {
103         va_list ap;
104         unsigned ret;
105
106         va_start(ap, fmt);
107         ret = xvasprintf(result, fmt, ap);
108         va_end(ap);
109         return ret;
110 }
111
112 /*
113  * Compile a regular expression.
114  *
115  * This simple wrapper calls regcomp(3) and logs a message on errors.
116  */
117 int xregcomp(regex_t *preg, const char *regex, int cflags)
118 {
119         char *buf;
120         size_t size;
121         int ret = regcomp(preg, regex, cflags);
122
123         if (ret == 0)
124                 return 1;
125         size = regerror(ret, preg, NULL, 0);
126         buf = xmalloc(size);
127         regerror(ret, preg, buf, size);
128         ERROR_LOG("%s\n", buf);
129         free(buf);
130         return -E_REGEX;
131 }
132
133 static int loglevel_arg_val;
134
135 __attribute__ ((format (printf, 2, 3)))
136 void txp_log(int ll, const char* fmt,...)
137 {
138         va_list argp;
139         if (ll < loglevel_arg_val)
140                 return;
141         va_start(argp, fmt);
142         vfprintf(stderr, fmt, argp);
143         va_end(argp);
144 }