205c8c9e9df7b247cdc38608b79ed4b90cf605aa
[mmh] / sbr / brkstring.c
1 /*
2 ** brkstring.c -- (destructively) split a string into
3 **             -- an array of substrings
4 **
5 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
6 ** COPYRIGHT file in the root directory of the nmh distribution for
7 ** complete copyright information.
8 */
9
10 #include <sysexits.h>
11 #include <h/mh.h>
12 #include <h/utils.h>
13
14 /* allocate this number of pointers at a time */
15 #define NUMBROKEN 256
16
17 static char **broken = NULL;    /* array of substring start addresses */
18 static int len = 0;             /* current size of "broken"           */
19
20
21 /*
22 ** returns pointer to static memory
23 */
24 char **
25 brkstring(char *str, char *brksep, char *brkterm)
26 {
27         int i;
28         char c, *s;
29
30         /* allocate initial space for pointers on first call */
31         if (!broken) {
32                 len = NUMBROKEN;
33                 broken = (char **)mh_xmalloc((size_t)(len * sizeof(*broken)));
34         }
35
36         /*
37         ** scan string, replacing separators with zeroes
38         ** and enter start addresses in "broken".
39         */
40         s = str;
41         for (i = 0;; i++) {
42                 /* enlarge pointer array, if necessary */
43                 if (i >= len) {
44                         len += NUMBROKEN;
45                         broken = mh_xrealloc(broken,
46                                         (size_t)(len * sizeof(*broken)));
47                 }
48
49                 /* handle separators */
50                 while ((c=*s) && brksep && strchr(brksep, c)) {
51                         *s++ = '\0';
52                 }
53
54                 /*
55                 ** we are either at the end of the string, or the
56                 ** terminator found has been found, so finish up.
57                 */
58                 if (!c || (brkterm && strchr(brkterm, c))) {
59                         *s = '\0';
60                         broken[i] = NULL;
61                         return broken;
62                 }
63
64                 /* set next start addr and walk over word */
65                 broken[i] = s;
66                 while ((c = *++s)) {
67                         if (brksep && strchr(brksep, c)) {
68                                 break;
69                         }
70                         if (brkterm && strchr(brkterm, c)) {
71                                 break;
72                         }
73                 }
74         }
75         adios(EX_SOFTWARE, "brkstring()", "reached unreachable point");
76 }