/* xutil.c - Various wrapper functions to abort on error. * * Copyright © 2009 Carl Worth * * 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 3 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 http://www.gnu.org/licenses/ . * * Author: Carl Worth */ #define _GNU_SOURCE /* For strndup */ #include "notmuch-private.h" #include void * xcalloc (size_t nmemb, size_t size) { void *ret; ret = calloc (nmemb, size); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } return ret; } void * xmalloc (size_t size) { void *ret; ret = malloc (size); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } return ret; } void * xrealloc (void *ptr, size_t size) { void *ret; ret = realloc (ptr, size); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } return ret; } char * xstrdup (const char *s) { char *ret; ret = strdup (s); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } return ret; } #ifdef __APPLE__ /* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ char *strndup (const char *s, size_t n) { size_t len = strlen (s); char *ret; if (len <= n) return strdup (s); ret = malloc(n + 1); strncpy(ret, s, n); ret[n] = '\0'; return ret; } /* getline implementation is copied from glibc. */ #ifndef SIZE_MAX # define SIZE_MAX ((size_t) -1) #endif #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif ssize_t getline (char **lineptr, size_t *n, FILE *fp) { ssize_t result; size_t cur_len = 0; if (lineptr == NULL || n == NULL || fp == NULL) { errno = EINVAL; return -1; } if (*lineptr == NULL || *n == 0) { *n = 120; *lineptr = (char *) malloc (*n); if (*lineptr == NULL) { result = -1; goto end; } } for (;;) { int i; i = getc (fp); if (i == EOF) { result = -1; break; } /* Make enough space for len+1 (for final NUL) bytes. */ if (cur_len + 1 >= *n) { size_t needed_max = SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; size_t needed = 2 * *n + 1; /* Be generous. */ char *new_lineptr; if (needed_max < needed) needed = needed_max; if (cur_len + 1 >= needed) { result = -1; goto end; } new_lineptr = (char *) realloc (*lineptr, needed); if (new_lineptr == NULL) { result = -1; goto end; } *lineptr = new_lineptr; *n = needed; } (*lineptr)[cur_len] = i; cur_len++; if (i == '\n') break; } (*lineptr)[cur_len] = '\0'; result = cur_len ? (ssize_t) cur_len : result; end: return result; } #endif char * xstrndup (const char *s, size_t n) { char *ret; ret = strndup (s, n); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } return ret; } void xregcomp (regex_t *preg, const char *regex, int cflags) { int rerr; rerr = regcomp (preg, regex, cflags); if (rerr) { size_t error_size = regerror (rerr, preg, NULL, 0); char *error = xmalloc (error_size); regerror (rerr, preg, error, error_size); INTERNAL_ERROR ("compiling regex %s: %s\n", regex, error); } } int xregexec (const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { unsigned int i; int rerr; rerr = regexec (preg, string, nmatch, pmatch, eflags); if (rerr) return rerr; for (i = 0; i < nmatch; i++) { if (pmatch[i].rm_so == -1) INTERNAL_ERROR ("matching regex against %s: Sub-match %d not found\n", string, i); } return 0; }