27f187e2e72daaf9ff2b3a1b96e740a7977ee115
[mmh] / sbr / brkstring.c
1
2 /*
3  * brkstring.c -- (destructively) split a string into
4  *             -- an array of substrings
5  *
6  * $Id$
7  *
8  * This code is Copyright (c) 2002, by the authors of nmh.  See the
9  * COPYRIGHT file in the root directory of the nmh distribution for
10  * complete copyright information.
11  */
12
13 #include <h/mh.h>
14
15 /* allocate this number of pointers at a time */
16 #define NUMBROKEN 256
17
18 static char **broken = NULL;    /* array of substring start addresses */
19 static int len = 0;             /* current size of "broken"           */
20
21 /*
22  * static prototypes
23  */
24 static int brkany (char, char *);
25
26
27 char **
28 brkstring (char *str, char *brksep, char *brkterm)
29 {
30     int i;
31     char c, *s;
32
33     /* allocate initial space for pointers on first call */
34     if (!broken) {
35         len = NUMBROKEN;
36         if (!(broken = (char **) malloc ((size_t) (len * sizeof(*broken)))))
37             adios (NULL, "unable to malloc array in brkstring");
38     }
39
40     /*
41      * scan string, replacing separators with zeroes
42      * and enter start addresses in "broken".
43      */
44     s = str;
45
46     for (i = 0;; i++) {
47
48         /* enlarge pointer array, if necessary */
49         if (i >= len) {
50             len += NUMBROKEN;
51             if (!(broken = realloc (broken, (size_t) (len * sizeof(*broken)))))
52                 adios (NULL, "unable to realloc array in brkstring");
53         }
54
55         while (brkany (c = *s, brksep))
56             *s++ = '\0';
57
58         /*
59          * we are either at the end of the string, or the
60          * terminator found has been found, so finish up.
61          */
62         if (!c || brkany (c, brkterm)) {
63             *s = '\0';
64             broken[i] = NULL;
65             return broken;
66         }
67
68         /* set next start addr */
69         broken[i] = s;
70
71         while ((c = *++s) && !brkany (c, brksep) && !brkany (c, brkterm))
72             ;   /* empty body */
73     }
74
75     return broken;      /* NOT REACHED */
76 }
77
78
79 /*
80  * If the character is in the string,
81  * return 1, else return 0.
82  */
83
84 static int
85 brkany (char c, char *str)
86 {
87     char *s;
88
89     if (str) {
90         for (s = str; *s; s++)
91             if (c == *s)
92                 return 1;
93     }
94     return 0;
95 }