1 /* $Id$
2 * Provides funstions to operate dinamically allocated strings.
3
4 * Copyright (C) 1997-2000
5 *
6 * Kolya Nesterov
7 *
8 * Fido: 2:463/567
9 * Kiev, Ukraine
10 *
11 * Latest version may be foind on http://husky.sourceforge.net
12 *
13 *
14 * HUSKYLIB: common defines, types and functions for HUSKY
15 *
16 * This is part of The HUSKY Fidonet Software project:
17 * see http://husky.sourceforge.net for details
18 *
19 *
20 * HUSKYLIB is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2 of the License, or (at your option) any later version.
24 *
25 * HUSKYLIB is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; see file COPYING. If not, write to the
32 * Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 *
34 * See also http://www.gnu.org, license may be found here.
35 */
36
37 /* standard headers */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42
43
44 /* huskylib: compiler.h */
45 #include <compiler.h>
46
47 /* huskylib headers */
48 #define DLLEXPORT
49 #include <huskyext.h>
50
51 /* huskylib headers */
52 #include <memory.h>
53 #include <xstr.h>
54
55
56 /*** Declarations & defines ***********************************************/
57
58 #if defined(VSPRINTF_ONLY)
59 #undef HAS_vsnprintf
60 #undef HAS_vasprintf
61 #endif
62
63 #define N_PRINTFBUF 1024
64
65 /*** Implementation *******************************************************/
66
xstralloc(char ** s,size_t add)67 char *xstralloc(char **s, size_t add)
68 {
69 int n;
70 if (*s == NULL) {
71 *s = smalloc(add + 1); **s = '\0'; n = 0;
72 } else {
73 *s = srealloc(*s, (n = strlen(*s)) + add + 1);
74 };
75 if (*s == NULL) {
76 fprintf(stderr, "out of memory");
77 abort();
78 }
79 return *s + n;
80 }
81
xstrcat(char ** s,const char * add)82 char *xstrcat(char **s, const char *add)
83 {
84 if(add == NULL)
85 return *s;
86 return strcat(xstralloc(s, strlen(add)), add);
87 }
88
xstrcpy(char ** s,const char * add)89 char *xstrcpy(char **s, const char *add)
90 {
91 nfree(*s);
92 return xstrcat(s, add);
93 }
94
95
xstrscat(char ** s,...)96 char *xstrscat(char **s, ...)
97 {
98 va_list ap;
99 char *q, *p;
100 int ncat;
101 for (va_start(ap, s), ncat = 0; (p = va_arg(ap, char *)) != NULLP; )
102 ncat += strlen(p);
103 va_end(ap);
104 p = xstralloc(s, ncat);
105 for (va_start(ap, s); (q = va_arg(ap, char *)) != NULLP; )
106 p = strcat(p, q);
107 va_end(ap);
108 return p;
109 }
110
xscatprintf(char ** s,const char * format,...)111 int xscatprintf(char **s, const char *format, ...)
112 {
113 va_list ap;
114 #if defined(HAS_vasprintf)
115 char *addline;
116 #elif defined(HAS_vsnprintf)
117 char *addline;
118 int nmax;
119 #else
120 char addline[N_PRINTFBUF];
121 #endif
122 int nprint;
123
124 va_start(ap, format);
125 #if defined(HAS_vasprintf)
126 vasprintf(&addline, format, ap);
127 #elif defined(HAS_vsnprintf)
128 addline = NULL;
129 for (nmax = N_PRINTFBUF; ; ) {
130 xstralloc(&addline, nmax);
131 nprint = vsnprintf(addline, nmax, format, ap);
132 /* If that worked, return the string. */
133 if (nprint > -1 && nprint < nmax)
134 break;
135 /* Else try again with more space. */
136 if (nprint > -1)
137 nmax = nprint+1; /* precisely what is needed */
138 else
139 nmax += N_PRINTFBUF; /* twice the old size */
140 };
141 #else
142 nprint = vsprintf(addline, format, ap);
143 if (nprint > N_PRINTFBUF) {
144 fprintf(stderr, "sprintf buffer overflow at xscatprintf.\n" \
145 "used %d bytes instead of %d\n" \
146 "format leading to this was : %s\n"\
147 "please tell the developers\n", nprint,
148 N_PRINTFBUF, format);
149 abort();
150 };
151 #endif
152 va_end(ap);
153 xstrcat(s, addline);
154 #if defined(HAS_vasprintf) || defined(HAS_vsnprintf)
155 free(addline);
156 #endif
157 return nprint;
158 }
159
160 #ifdef TEST
161
main(void)162 int main(void)
163 {
164 char *s = NULL;
165 xstralloc(&s, 10);
166 strcpy(s, "1234567890");
167 xstrcat(&s, " test");
168 xstrscat(&s, " this", " one", NULL);
169 xscatprintf(&s, " %d %d", 3, 4);
170 printf("%s", s);
171 return strcmp(s, "1234567890 test this one 3 4");
172 }
173
174 #endif
175