Use -lbsd for strlcat/strlcpy, if needed and available
[wmaker-crm.git] / WINGs / string.c
blobc86970f7026e13489582db7aa9e71c8d7be7906f
2 #include "wconfig.h"
4 #include <string.h>
5 #include <stdlib.h>
6 #include <ctype.h>
7 #ifdef HAVE_BSD_STRING_H
8 #include <bsd/string.h>
9 #endif
11 #include "WUtil.h"
13 #define PRC_ALPHA 0
14 #define PRC_BLANK 1
15 #define PRC_ESCAPE 2
16 #define PRC_DQUOTE 3
17 #define PRC_EOS 4
18 #define PRC_SQUOTE 5
20 typedef struct {
21 short nstate;
22 short output;
23 } DFA;
25 static DFA mtable[9][6] = {
26 {{3, 1}, {0, 0}, {4, 0}, {1, 0}, {8, 0}, {6, 0}},
27 {{1, 1}, {1, 1}, {2, 0}, {3, 0}, {5, 0}, {1, 1}},
28 {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {5, 0}, {1, 1}},
29 {{3, 1}, {5, 0}, {4, 0}, {1, 0}, {5, 0}, {6, 0}},
30 {{3, 1}, {3, 1}, {3, 1}, {3, 1}, {5, 0}, {3, 1}},
31 {{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
32 {{6, 1}, {6, 1}, {7, 0}, {6, 1}, {5, 0}, {3, 0}},
33 {{6, 1}, {6, 1}, {6, 1}, {6, 1}, {5, 0}, {6, 1}},
34 {{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
37 char *wtokennext(char *word, char **next)
39 char *ptr;
40 char *ret, *t;
41 int state, ctype;
43 t = ret = wmalloc(strlen(word) + 1);
44 ptr = word;
46 state = 0;
47 while (1) {
48 if (*ptr == 0)
49 ctype = PRC_EOS;
50 else if (*ptr == '\\')
51 ctype = PRC_ESCAPE;
52 else if (*ptr == '"')
53 ctype = PRC_DQUOTE;
54 else if (*ptr == '\'')
55 ctype = PRC_SQUOTE;
56 else if (*ptr == ' ' || *ptr == '\t')
57 ctype = PRC_BLANK;
58 else
59 ctype = PRC_ALPHA;
61 if (mtable[state][ctype].output) {
62 *t = *ptr;
63 t++;
64 *t = 0;
66 state = mtable[state][ctype].nstate;
67 ptr++;
68 if (mtable[state][0].output < 0) {
69 break;
73 if (*ret == 0)
74 t = NULL;
75 else
76 t = wstrdup(ret);
78 wfree(ret);
80 if (ctype == PRC_EOS)
81 *next = NULL;
82 else
83 *next = ptr;
85 return t;
88 /* separate a string in tokens, taking " and ' into account */
89 void wtokensplit(char *command, char ***argv, int *argc)
91 char *token, *line;
92 int count;
94 count = 0;
95 line = command;
96 do {
97 token = wtokennext(line, &line);
98 if (token) {
99 if (count == 0)
100 *argv = wmalloc(sizeof(char **));
101 else
102 *argv = wrealloc(*argv, (count + 1) * sizeof(char **));
103 (*argv)[count++] = token;
105 } while (token != NULL && line != NULL);
107 *argc = count;
110 char *wtokenjoin(char **list, int count)
112 int i, j;
113 char *flat_string, *wspace;
115 j = 0;
116 for (i = 0; i < count; i++) {
117 if (list[i] != NULL && list[i][0] != 0) {
118 j += strlen(list[i]);
119 if (strpbrk(list[i], " \t"))
120 j += 2;
124 flat_string = wmalloc(j + count + 1);
126 for (i = 0; i < count; i++) {
127 if (list[i] != NULL && list[i][0] != 0) {
128 if (i > 0)
129 strcat(flat_string, " ");
130 wspace = strpbrk(list[i], " \t");
131 if (wspace)
132 strcat(flat_string, "\"");
133 strcat(flat_string, list[i]);
134 if (wspace)
135 strcat(flat_string, "\"");
139 return flat_string;
142 void wtokenfree(char **tokens, int count)
144 while (count--)
145 wfree(tokens[count]);
146 wfree(tokens);
149 char *wtrimspace(const char *s)
151 char *t;
153 if (s == NULL)
154 return NULL;
156 while (isspace(*s) && *s)
157 s++;
158 t = (char *)s + strlen(s) - 1;
159 while (t > s && isspace(*t))
160 t--;
162 return wstrndup(s, t - s + 1);
165 char *wstrdup(const char *str)
167 assert(str != NULL);
169 return strcpy(wmalloc(strlen(str) + 1), str);
172 char *wstrndup(const char *str, size_t len)
174 char *copy;
176 assert(str != NULL);
178 len = WMIN(len, strlen(str));
179 copy = strncpy(wmalloc(len + 1), str, len);
180 copy[len] = 0;
182 return copy;
185 char *wstrconcat(char *str1, char *str2)
187 char *str;
189 if (!str1)
190 return wstrdup(str2);
191 else if (!str2)
192 return wstrdup(str1);
194 str = wmalloc(strlen(str1) + strlen(str2) + 1);
195 strcpy(str, str1);
196 strcat(str, str2);
198 return str;
201 char *wstrappend(char *dst, char *src)
203 if (!dst)
204 return wstrdup(src);
205 else if (!src || *src == 0)
206 return dst;
208 dst = wrealloc(dst, strlen(dst) + strlen(src) + 1);
209 strcat(dst, src);
211 return dst;
215 #ifdef HAVE_STRLCAT
216 size_t
217 wstrlcat(char *dst, const char *src, size_t siz)
219 return strlcat(dst, src, siz);
221 #else
222 /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
225 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
227 * Permission to use, copy, modify, and distribute this software for any
228 * purpose with or without fee is hereby granted, provided that the above
229 * copyright notice and this permission notice appear in all copies.
231 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
232 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
233 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
234 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
235 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
236 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
237 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
241 * Appends src to string dst of size siz (unlike strncat, siz is the
242 * full size of dst, not space left). At most siz-1 characters
243 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
244 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
245 * If retval >= siz, truncation occurred.
247 size_t
248 wstrlcat(char *dst, const char *src, size_t siz)
250 char *d = dst;
251 const char *s = src;
252 size_t n = siz;
253 size_t dlen;
255 /* Find the end of dst and adjust bytes left but don't go past end */
256 while (n-- != 0 && *d != '\0')
257 d++;
258 dlen = d - dst;
259 n = siz - dlen;
261 if (n == 0)
262 return(dlen + strlen(s));
263 while (*s != '\0') {
264 if (n != 1) {
265 *d++ = *s;
266 n--;
268 s++;
270 *d = '\0';
272 return(dlen + (s - src)); /* count does not include NUL */
274 #endif /* HAVE_STRLCAT */
276 #ifdef HAVE_STRLCPY
277 size_t
278 wstrlcpy(char *dst, const char *src, size_t siz)
280 return strlcpy(dst, src, siz);
282 #else
284 /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
287 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
289 * Permission to use, copy, modify, and distribute this software for any
290 * purpose with or without fee is hereby granted, provided that the above
291 * copyright notice and this permission notice appear in all copies.
293 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
294 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
295 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
296 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
297 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
298 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
299 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
303 * Copy src to string dst of size siz. At most siz-1 characters
304 * will be copied. Always NUL terminates (unless siz == 0).
305 * Returns strlen(src); if retval >= siz, truncation occurred.
307 size_t
308 wstrlcpy(char *dst, const char *src, size_t siz)
310 char *d = dst;
311 const char *s = src;
312 size_t n = siz;
314 /* Copy as many bytes as will fit */
315 if (n != 0) {
316 while (--n != 0) {
317 if ((*d++ = *s++) == '\0')
318 break;
322 /* Not enough room in dst, add NUL and traverse rest of src */
323 if (n == 0) {
324 if (siz != 0)
325 *d = '\0'; /* NUL-terminate dst */
326 while (*s++)
330 return(s - src - 1); /* count does not include NUL */
332 #endif /* HAVE_STRLCPY */