diff options
Diffstat (limited to 'mimetypes/err.c')
-rw-r--r-- | mimetypes/err.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/mimetypes/err.c b/mimetypes/err.c new file mode 100644 index 0000000..39f25a5 --- /dev/null +++ b/mimetypes/err.c @@ -0,0 +1,150 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> +#include "mtint.h" + +ssize_t +mimetypes_error_format (char **pbuf, size_t *psize, + struct locus_range const *lr, char const *fmt, + va_list ap) +{ + char *buf; + size_t buflen; + ssize_t n; + int rc; + + if (lr) + { + n = locus_range_format (pbuf, psize, lr); + if (n == -1) + return -1; + buf = *pbuf; + buflen = *psize; + } + else + { + buf = *pbuf; + buflen = *psize; + if (buflen == 0) + buflen = 512; /* Initial allocation */ + + buf = calloc (1, buflen); + if (buf == NULL) + { + errno = ENOMEM; + return -1; + } + } + + for (;;) + { + va_list aq; + + va_copy(aq, ap); + n = vsnprintf (buf, buflen, fmt, aq); + va_end(aq); + + if (n < 0 || n >= buflen || !memchr (buf, '\0', n + 1)) + { + char *newbuf; + size_t newlen = buflen * 2; + if (newlen < buflen) + { + errno = ENOMEM; + rc = -1; + break; + } + newbuf = realloc (buf, newlen); + if (newbuf == NULL) + { + errno = ENOMEM; + rc = -1; + break; + } + buflen = newlen; + buf = newbuf; + } + else + break; + } + + if (rc) + { + if (!*pbuf) + { + /* We made first allocation, now free it */ + free (buf); + buf = NULL; + buflen = 0; + } + } + + *pbuf = buf; + *psize = buflen; + return rc; +} + + +static void +default_error_printer (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +void (*mimetypes_error_printer) (char const *) = default_error_printer; + +void +mimetypes_error_at (struct locus_range const *lr, char const *fmt, ...) +{ + va_list ap; + char *buf = NULL; + size_t buflen = 0; + ssize_t n; + + va_start (ap, fmt); + n = mimetypes_error_format (&buf, &buflen, lr, fmt, ap); + va_end (ap); + + if (n < 0) + return; + + mimetypes_error_printer (buf); + + free (buf); +} + +void +mimetypes_error (char const *fmt, ...) +{ + va_list ap; + char *buf = NULL; + size_t buflen = 0; + ssize_t n; + + va_start (ap, fmt); + n = mimetypes_error_format (&buf, &buflen, NULL, fmt, ap); + va_end (ap); + + if (n < 0) + return; + + mimetypes_error_printer (buf); + + free (buf); +} + +void +print_locus_range (FILE *fp, struct locus_range const *lr) +{ + char *buf = NULL; + size_t buflen = 0; + ssize_t n; + n = locus_range_format (&buf, &buflen, lr); + if (n < 0) + return; + fwrite (buf, buflen, 1, fp); + free (buf); +} |