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