/* $Id: xstr.c,v 1.4.4.2 2002/10/24 13:13:49 stas_degteff Exp $ */ /***************************************************************************** * String utilities for HPT (FTN NetMail/EchoMail Tosser) ***************************************************************************** * Copyright (C) 1997-2000 * * Kolya Nesterov * * Fido: 2:463/567 * Kiev, Ukraine * * This file is part of FIDOCONFIG. * * HPT 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, or (at your option) any * later version. * * HPT 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 HPT; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************/ #include #include #include #include #include "xstr.h" #include "common.h" #if defined(VSPRINTF_ONLY) #undef HAS_VSNPRINTF #undef HAS_VASPRINTF #endif #define N_PRINTFBUF 1024 char *xstralloc(char **s, size_t add) { int n; if (*s == NULL) { *s = smalloc(add + 1); **s = '\0'; n = 0; } else { *s = srealloc(*s, (n = strlen(*s)) + add + 1); }; if (*s == NULL) { fprintf(stderr, "out of memory"); abort(); } return *s + n; } char *xstrcat(char **s, char *add) { return strcat(xstralloc(s, strlen(add)), add); } char *xstrscat(char **s, ...) { va_list ap; char *q, *p; int ncat; for (va_start(ap, s), ncat = 0; (p = va_arg(ap, char *)) != NULL; ) ncat += strlen(p); p = xstralloc(s, ncat); for (va_start(ap, s); (q = va_arg(ap, char *)) != NULL; ) p = strcat(p, q); return p; } int xscatprintf(char **s, const char *format, ...) { va_list ap; #if defined(HAS_VASPRINTF) char *addline; #elif defined(HAS_VSNPRINTF) char *addline; int nmax; #else char addline[N_PRINTFBUF]; #endif int nprint; va_start(ap, format); #if defined(HAS_VASPRINTF) vasprintf(&addline, format, ap); #elif defined(HAS_VSNPRINTF) addline = NULL; for (nmax = N_PRINTFBUF; ; ) { xstralloc(&addline, nmax); nprint = vsnprintf(addline, nmax, format, ap); /* If that worked, return the string. */ if (nprint > -1 && nprint < nmax) break; /* Else try again with more space. */ if (nprint > -1) nmax = nprint+1; /* precisely what is needed */ else nmax += N_PRINTFBUF; /* twice the old size */ }; #else nprint = vsprintf(addline, format, ap); if (nprint > N_PRINTFBUF) { fprintf(stderr, "sprintf buffer overflow at xscatprintf.\n" \ "used %d bytes instead of %d\n" \ "format leading to this was : %s\n"\ "please tell the developers\n", nprint, N_PRINTFBUF, format); abort(); }; #endif va_end(ap); xstrcat(s, addline); #if defined(HAS_VASPRINTF) || defined(HAS_VSNPRINTF) free(addline); #endif return nprint; } #ifdef TEST int main(void) { char *s = NULL; xstralloc(&s, 10); strcpy(s, "1234567890"); xstrcat(&s, " test"); xstrscat(&s, " this", " one", NULL); xscatprintf(&s, " %d %d", 3, 4); printf("%s", s); return strcmp(s, "1234567890 test this one 3 4"); } #endif