/* Yash: yet another shell */
/* util.h: miscellaneous utility functions */
/* (C) 2007-2011 magicant */
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see . */
#ifndef YASH_UTIL_H
#define YASH_UTIL_H
#include
#define Size_max ((size_t) -1) // = SIZE_MAX
/********** General Functions **********/
static inline void *xcalloc(size_t nmemb, size_t size)
__attribute__((malloc,warn_unused_result));
static inline void *xmalloc(size_t size)
__attribute__((malloc,warn_unused_result));
static inline void *xmallocn(size_t count, size_t elemsize)
__attribute__((malloc,warn_unused_result));
static inline void *xmallocs(size_t mainsize, size_t count, size_t elemsize)
__attribute__((malloc,warn_unused_result));
static inline void *xrealloc(void *ptr, size_t size)
__attribute__((malloc,warn_unused_result));
static inline void *xreallocn(void *ptr, size_t count, size_t elemsize)
__attribute__((malloc,warn_unused_result));
static inline void *xreallocs(void *ptr,
size_t mainsize, size_t count, size_t elemsize)
__attribute__((malloc,warn_unused_result));
extern size_t addmul(size_t mainsize, size_t count, size_t elemsize)
__attribute__((pure));
extern void alloc_failed(void)
__attribute__((noreturn));
/* Attempts `calloc' and aborts the program on failure. */
void *xcalloc(size_t nmemb, size_t size)
{
void *result = calloc(nmemb, size);
if (result == NULL)
alloc_failed();
return result;
}
/* Attempts `malloc' and aborts the program on failure. */
void *xmalloc(size_t size)
{
void *result = malloc(size);
if (result == NULL && size > 0)
alloc_failed();
return result;
}
/* Like `xmalloc(count * elemsize)', but aborts the program if the size is too
* large. `elemsize' must not be zero. */
void *xmallocn(size_t count, size_t elemsize)
{
return xmallocs(0, count, elemsize);
}
/* Like `xmalloc(mainsize + count * elemsize)', but aborts the program if the
* size is too large. `elemsize' must not be zero. */
void *xmallocs(size_t mainsize, size_t count, size_t elemsize)
{
return xmalloc(addmul(mainsize, count, elemsize));
}
/* Attempts `realloc' and aborts the program on failure. */
void *xrealloc(void *ptr, size_t size)
{
void *result = realloc(ptr, size);
if (result == NULL && size > 0)
alloc_failed();
return result;
}
/* Like `xrealloc(ptr, count * elemsize)', but aborts the program if the size is
* too large. `elemsize' must not be zero. */
void *xreallocn(void *ptr, size_t count, size_t elemsize)
{
return xreallocs(ptr, 0, count, elemsize);
}
/* Like `xrealloc(mainsize + count * elemsize)', but aborts the program if the
* size is too large. `elemsize' must not be zero. */
void *xreallocs(void *ptr, size_t mainsize, size_t count, size_t elemsize)
{
return xrealloc(ptr, addmul(mainsize, count, elemsize));
}
/********** String Utilities **********/
extern size_t xstrnlen(const char *s, size_t maxlen)
__attribute__((pure,nonnull));
extern char *xstrndup(const char *s, size_t maxlen)
__attribute__((malloc,warn_unused_result,nonnull));
static inline char *xstrdup(const char *s)
__attribute__((malloc,warn_unused_result,nonnull));
extern size_t xwcsnlen(const wchar_t *s, size_t maxlen)
__attribute__((pure,nonnull));
extern wchar_t *xwcsndup(const wchar_t *s, size_t maxlen)
__attribute__((malloc,warn_unused_result,nonnull));
static inline wchar_t *xwcsdup(const wchar_t *s)
__attribute__((malloc,warn_unused_result,nonnull));
extern _Bool xstrtoi(const char *s, int base, int *resultp)
__attribute__((warn_unused_result,nonnull));
extern _Bool xwcstoi(const wchar_t *s, int base, int *resultp)
__attribute__((warn_unused_result,nonnull));
extern _Bool xwcstol(const wchar_t *s, int base, long *resultp)
__attribute__((warn_unused_result,nonnull));
extern _Bool xwcstoul(const wchar_t *s, int base, unsigned long *resultp)
__attribute__((warn_unused_result,nonnull));
extern char *matchstrprefix(const char *s, const char *prefix)
__attribute__((pure,nonnull));
extern wchar_t *matchwcsprefix(const wchar_t *s, const wchar_t *prefix)
__attribute__((pure,nonnull));
extern void *copyaswcs(const void *p)
__attribute__((malloc,warn_unused_result,nonnull));
#if HAVE_STRNLEN
# ifndef strnlen
extern size_t strnlen(const char *s, size_t maxlen);
# endif
# define xstrnlen(s,maxlen) strnlen(s,maxlen)
#endif
#if HAVE_WCSNLEN
# ifndef wcsnlen
extern size_t wcsnlen(const wchar_t *s, size_t maxlen);
# endif
# define xwcsnlen(s,maxlen) wcsnlen(s,maxlen)
#endif
/* Returns a newly malloced copy of the specified string.
* Aborts the program if failed to allocate memory. */
char *xstrdup(const char *s)
{
return xstrndup(s, Size_max);
}
/* Returns a newly malloced copy of the specified string.
* Aborts the program if failed to allocate memory. */
wchar_t *xwcsdup(const wchar_t *s)
{
return xwcsndup(s, Size_max);
}
/* These macros are used to cast the argument properly.
* We don't need such macros for wide characters. */
#define xisalnum(c) (isalnum((unsigned char) (c)))
#define xisalpha(c) (isalpha((unsigned char) (c)))
#define xisblank(c) (isblank((unsigned char) (c)))
#define xiscntrl(c) (iscntrl((unsigned char) (c)))
#define xisdigit(c) (isdigit((unsigned char) (c)))
#define xisgraph(c) (isgraph((unsigned char) (c)))
#define xislower(c) (islower((unsigned char) (c)))
#define xisprint(c) (isprint((unsigned char) (c)))
#define xispunct(c) (ispunct((unsigned char) (c)))
#define xisspace(c) (isspace((unsigned char) (c)))
#define xisupper(c) (isupper((unsigned char) (c)))
#define xisxdigit(c) (isxdigit((unsigned char) (c)))
#define xtoupper(c) (toupper((unsigned char) (c)))
#define xtolower(c) (tolower((unsigned char) (c)))
/* Casts scalar to char safely. */
#define TO_CHAR(value) \
((union { char c; unsigned char uc; }) { .uc = (unsigned char) (value), }.c)
/********** Error Utilities **********/
extern const wchar_t *yash_program_invocation_name;
extern const wchar_t *yash_program_invocation_short_name;
extern const wchar_t *current_builtin_name;
extern unsigned yash_error_message_count;
extern void xerror(int errno_, const char *restrict format, ...)
__attribute__((format(printf,2,3)));
extern _Bool xprintf(const char *restrict format, ...)
__attribute__((format(printf,1,2)));
/********** xgetopt **********/
extern wchar_t *xoptarg;
extern int xoptind;
enum xgetoptopt_T {
XGETOPT_POSIX = 1 << 0,
XGETOPT_DIGIT = 1 << 1,
};
enum optarg_T {
OPTARG_NONE, OPTARG_REQUIRED, OPTARG_OPTIONAL,
};
struct xgetopt_T {
wchar_t shortopt;
const wchar_t *longopt;
enum optarg_T optarg;
_Bool posix;
void *ptr;
};
extern struct xgetopt_T *xgetopt(
void **restrict argv,
const struct xgetopt_T *restrict opts,
enum xgetoptopt_T opt)
__attribute__((nonnull));
#undef Size_max
#endif /* YASH_UTIL_H */
/* vim: set ts=8 sts=4 sw=4 noet tw=80: */