1 /* Yash: yet another shell */
2 /* util.h: miscellaneous utility functions */
3 /* (C) 2007-2021 magicant */
5 /* This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #define Size_max ((size_t) -1) // = SIZE_MAX
27 /********** Miscellaneous Functions **********/
29 static inline int xunsetenv(const char *name)
30 __attribute__((nonnull));
32 /* Removes the environment variable of the specified name.
33 * This function wraps the `unsetenv' function, which has an incompatible
34 * prototype on some old environments. */
35 int xunsetenv(const char *name)
37 #if UNSETENV_RETURNS_INT
38 return unsetenv(name);
46 /********** Memory Functions **********/
48 static inline size_t add(size_t a, size_t b)
49 __attribute__((pure));
50 static inline size_t mul(size_t a, size_t b)
51 __attribute__((pure));
53 static inline void *xcalloc(size_t nmemb, size_t size)
54 __attribute__((malloc,warn_unused_result));
55 static inline void *xmalloc(size_t size)
56 __attribute__((malloc,warn_unused_result));
57 static inline void *xmallocn(size_t count, size_t elemsize)
58 __attribute__((malloc,warn_unused_result));
59 static inline void *xmalloce(size_t count1, size_t count2, size_t elemsize)
60 __attribute__((malloc,warn_unused_result));
61 static inline void *xmallocs(size_t mainsize, size_t count, size_t elemsize)
62 __attribute__((malloc,warn_unused_result));
63 static inline void *xrealloc(void *ptr, size_t size)
64 __attribute__((malloc,warn_unused_result));
65 static inline void *xreallocn(void *ptr, size_t count, size_t elemsize)
66 __attribute__((malloc,warn_unused_result));
67 static inline void *xrealloce(void *ptr,
68 size_t count1, size_t count2, size_t elemsize)
69 __attribute__((malloc,warn_unused_result));
70 static inline void *xreallocs(void *ptr,
71 size_t mainsize, size_t count, size_t elemsize)
72 __attribute__((malloc,warn_unused_result));
73 extern void alloc_failed(void)
74 __attribute__((noreturn));
76 /* Computes `a + b', but aborts the program by ENOMEM if the result overflows.
78 size_t add(size_t a, size_t b)
86 /* Computes `a * b', but aborts the program by ENOMEM if the result overflows.
88 size_t mul(size_t a, size_t b)
90 size_t product = a * b;
91 if (b != 0 && product / b != a)
96 /* Attempts `calloc' and aborts the program on failure. */
97 void *xcalloc(size_t nmemb, size_t size)
99 void *result = calloc(nmemb, size);
100 if (result == NULL && nmemb > 0 && size > 0)
105 /* Attempts `malloc' and aborts the program on failure. */
106 void *xmalloc(size_t size)
108 void *result = malloc(size);
109 if (result == NULL && size > 0)
114 /* Like `xmalloc(count * elemsize)', but aborts the program if the size is too
116 void *xmallocn(size_t count, size_t elemsize)
118 return xmalloc(mul(count, elemsize));
121 /* Like `xmalloc((count1 + count2) * elemsize)', but aborts the program if the
122 * size is too large. */
123 void *xmalloce(size_t count1, size_t count2, size_t elemsize)
125 return xmallocn(add(count1, count2), elemsize);
128 /* Like `xmalloc(mainsize + count * elemsize)', but aborts the program if the
129 * size is too large. */
130 void *xmallocs(size_t mainsize, size_t count, size_t elemsize)
132 return xmalloc(add(mainsize, mul(count, elemsize)));
135 /* Attempts `realloc' and aborts the program on failure. */
136 void *xrealloc(void *ptr, size_t size)
138 /* The behavior of `realloc(non_null_pointer, 0)' is unreliable. Some
139 * implementations free the previously allocated region and return NULL.
140 * Some reallocate an empty region and return a pointer to it. The latter
141 * may fail to allocate the new region, leaving the previous region intact
142 * and returning NULL. That means, when `realloc(non_null_pointer, 0)'
143 * returned NULL, we cannot tell if the previous region has been freed or
150 void *result = realloc(ptr, size);
156 /* Like `xrealloc(ptr, count * elemsize)', but aborts the program if the size is
158 void *xreallocn(void *ptr, size_t count, size_t elemsize)
160 return xrealloc(ptr, mul(count, elemsize));
163 /* Like `xrealloc(ptr, (count1 + count2) * elemsize)', but aborts the program if
164 * the size is too large. */
165 void *xrealloce(void *ptr, size_t count1, size_t count2, size_t elemsize)
167 return xreallocn(ptr, add(count1, count2), elemsize);
170 /* Like `xrealloc(ptr, mainsize + count * elemsize)', but aborts the program if
171 * the size is too large. */
172 void *xreallocs(void *ptr, size_t mainsize, size_t count, size_t elemsize)
174 return xrealloc(ptr, add(mainsize, mul(count, elemsize)));
178 /********** String Utilities **********/
181 extern size_t xstrnlen(const char *s, size_t maxlen)
182 __attribute__((pure,nonnull));
185 extern char *xstrdup(const char *s)
186 __attribute__((malloc,warn_unused_result,nonnull));
189 extern size_t xwcsnlen(const wchar_t *s, size_t maxlen)
190 __attribute__((pure,nonnull));
192 extern wchar_t *xwcsndup(const wchar_t *s, size_t maxlen)
193 __attribute__((malloc,warn_unused_result,nonnull));
195 static inline wchar_t *xwcsdup(const wchar_t *s)
196 __attribute__((malloc,warn_unused_result,nonnull));
198 extern _Bool xstrtoi(const char *s, int base, int *resultp)
199 __attribute__((warn_unused_result,nonnull));
200 extern _Bool xwcstoi(const wchar_t *s, int base, int *resultp)
201 __attribute__((warn_unused_result,nonnull));
202 extern _Bool xwcstol(const wchar_t *s, int base, long *resultp)
203 __attribute__((warn_unused_result,nonnull));
204 extern _Bool xwcstoul(const wchar_t *s, int base, unsigned long *resultp)
205 __attribute__((warn_unused_result,nonnull));
206 extern char *matchstrprefix(const char *s, const char *prefix)
207 __attribute__((pure,nonnull));
208 extern wchar_t *matchwcsprefix(const wchar_t *s, const wchar_t *prefix)
209 __attribute__((pure,nonnull));
210 extern void *copyaswcs(const void *p)
211 __attribute__((malloc,warn_unused_result,nonnull));
215 extern size_t strnlen(const char *s, size_t maxlen);
217 # define xstrnlen strnlen
222 extern char *strdup(const char *s);
224 # define xstrdup strdup
229 extern size_t wcsnlen(const wchar_t *s, size_t maxlen);
231 # define xwcsnlen wcsnlen
236 extern wchar_t *wcsdup(const wchar_t *s);
238 # define xwcsdup wcsdup
240 /* Returns a newly malloced copy of the specified string.
241 * Aborts the program if failed to allocate memory. */
242 wchar_t *xwcsdup(const wchar_t *s)
244 return xwcsndup(s, Size_max);
249 /* These macros are used to cast the argument properly.
250 * We don't need such macros for wide characters. */
251 #define xisalnum(c) (isalnum((unsigned char) (c)))
252 #define xisalpha(c) (isalpha((unsigned char) (c)))
253 #define xisblank(c) (isblank((unsigned char) (c)))
254 #define xiscntrl(c) (iscntrl((unsigned char) (c)))
255 #define xisdigit(c) (isdigit((unsigned char) (c)))
256 #define xisgraph(c) (isgraph((unsigned char) (c)))
257 #define xislower(c) (islower((unsigned char) (c)))
258 #define xisprint(c) (isprint((unsigned char) (c)))
259 #define xispunct(c) (ispunct((unsigned char) (c)))
260 #define xisspace(c) (isspace((unsigned char) (c)))
261 #define xisupper(c) (isupper((unsigned char) (c)))
262 #define xisxdigit(c) (isxdigit((unsigned char) (c)))
263 #define xtoupper(c) (toupper((unsigned char) (c)))
264 #define xtolower(c) (tolower((unsigned char) (c)))
267 /* Casts scalar to char safely. */
268 #define TO_CHAR(value) \
269 ((union { char c; unsigned char uc; }) { .uc = (unsigned char) (value), }.c)
272 /********** Error Utilities **********/
274 extern const wchar_t *yash_program_invocation_name;
275 extern const wchar_t *yash_program_invocation_short_name;
276 extern const wchar_t *current_builtin_name;
277 extern unsigned yash_error_message_count;
278 extern void xerror(int errno_, const char *restrict format, ...)
279 __attribute__((format(printf,2,3)));
281 extern _Bool xprintf(const char *restrict format, ...)
282 __attribute__((format(printf,1,2)));
287 #endif /* YASH_UTIL_H */
290 /* vim: set ts=8 sts=4 sw=4 et tw=80: */