diff options
Diffstat (limited to 'src/regress/lib/libc/regex/split.c')
-rw-r--r-- | src/regress/lib/libc/regex/split.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/regress/lib/libc/regex/split.c b/src/regress/lib/libc/regex/split.c new file mode 100644 index 0000000000..dd1ca14480 --- /dev/null +++ b/src/regress/lib/libc/regex/split.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* $NetBSD: split.c,v 1.2 1995/04/20 22:39:57 cgd Exp $ */ | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <string.h> | ||
5 | |||
6 | /* | ||
7 | - split - divide a string into fields, like awk split() | ||
8 | = int split(char *string, char *fields[], int nfields, char *sep); | ||
9 | */ | ||
10 | int /* number of fields, including overflow */ | ||
11 | split(string, fields, nfields, sep) | ||
12 | char *string; | ||
13 | char *fields[]; /* list is not NULL-terminated */ | ||
14 | int nfields; /* number of entries available in fields[] */ | ||
15 | char *sep; /* "" white, "c" single char, "ab" [ab]+ */ | ||
16 | { | ||
17 | register char *p = string; | ||
18 | register char c; /* latest character */ | ||
19 | register char sepc = sep[0]; | ||
20 | register char sepc2; | ||
21 | register int fn; | ||
22 | register char **fp = fields; | ||
23 | register char *sepp; | ||
24 | register int trimtrail; | ||
25 | |||
26 | /* white space */ | ||
27 | if (sepc == '\0') { | ||
28 | while ((c = *p++) == ' ' || c == '\t') | ||
29 | continue; | ||
30 | p--; | ||
31 | trimtrail = 1; | ||
32 | sep = " \t"; /* note, code below knows this is 2 long */ | ||
33 | sepc = ' '; | ||
34 | } else | ||
35 | trimtrail = 0; | ||
36 | sepc2 = sep[1]; /* now we can safely pick this up */ | ||
37 | |||
38 | /* catch empties */ | ||
39 | if (*p == '\0') | ||
40 | return(0); | ||
41 | |||
42 | /* single separator */ | ||
43 | if (sepc2 == '\0') { | ||
44 | fn = nfields; | ||
45 | for (;;) { | ||
46 | *fp++ = p; | ||
47 | fn--; | ||
48 | if (fn == 0) | ||
49 | break; | ||
50 | while ((c = *p++) != sepc) | ||
51 | if (c == '\0') | ||
52 | return(nfields - fn); | ||
53 | *(p-1) = '\0'; | ||
54 | } | ||
55 | /* we have overflowed the fields vector -- just count them */ | ||
56 | fn = nfields; | ||
57 | for (;;) { | ||
58 | while ((c = *p++) != sepc) | ||
59 | if (c == '\0') | ||
60 | return(fn); | ||
61 | fn++; | ||
62 | } | ||
63 | /* not reached */ | ||
64 | } | ||
65 | |||
66 | /* two separators */ | ||
67 | if (sep[2] == '\0') { | ||
68 | fn = nfields; | ||
69 | for (;;) { | ||
70 | *fp++ = p; | ||
71 | fn--; | ||
72 | while ((c = *p++) != sepc && c != sepc2) | ||
73 | if (c == '\0') { | ||
74 | if (trimtrail && **(fp-1) == '\0') | ||
75 | fn++; | ||
76 | return(nfields - fn); | ||
77 | } | ||
78 | if (fn == 0) | ||
79 | break; | ||
80 | *(p-1) = '\0'; | ||
81 | while ((c = *p++) == sepc || c == sepc2) | ||
82 | continue; | ||
83 | p--; | ||
84 | } | ||
85 | /* we have overflowed the fields vector -- just count them */ | ||
86 | fn = nfields; | ||
87 | while (c != '\0') { | ||
88 | while ((c = *p++) == sepc || c == sepc2) | ||
89 | continue; | ||
90 | p--; | ||
91 | fn++; | ||
92 | while ((c = *p++) != '\0' && c != sepc && c != sepc2) | ||
93 | continue; | ||
94 | } | ||
95 | /* might have to trim trailing white space */ | ||
96 | if (trimtrail) { | ||
97 | p--; | ||
98 | while ((c = *--p) == sepc || c == sepc2) | ||
99 | continue; | ||
100 | p++; | ||
101 | if (*p != '\0') { | ||
102 | if (fn == nfields+1) | ||
103 | *p = '\0'; | ||
104 | fn--; | ||
105 | } | ||
106 | } | ||
107 | return(fn); | ||
108 | } | ||
109 | |||
110 | /* n separators */ | ||
111 | fn = 0; | ||
112 | for (;;) { | ||
113 | if (fn < nfields) | ||
114 | *fp++ = p; | ||
115 | fn++; | ||
116 | for (;;) { | ||
117 | c = *p++; | ||
118 | if (c == '\0') | ||
119 | return(fn); | ||
120 | sepp = sep; | ||
121 | while ((sepc = *sepp++) != '\0' && sepc != c) | ||
122 | continue; | ||
123 | if (sepc != '\0') /* it was a separator */ | ||
124 | break; | ||
125 | } | ||
126 | if (fn < nfields) | ||
127 | *(p-1) = '\0'; | ||
128 | for (;;) { | ||
129 | c = *p++; | ||
130 | sepp = sep; | ||
131 | while ((sepc = *sepp++) != '\0' && sepc != c) | ||
132 | continue; | ||
133 | if (sepc == '\0') /* it wasn't a separator */ | ||
134 | break; | ||
135 | } | ||
136 | p--; | ||
137 | } | ||
138 | |||
139 | /* not reached */ | ||
140 | } | ||
141 | |||
142 | #ifdef TEST_SPLIT | ||
143 | |||
144 | |||
145 | /* | ||
146 | * test program | ||
147 | * pgm runs regression | ||
148 | * pgm sep splits stdin lines by sep | ||
149 | * pgm str sep splits str by sep | ||
150 | * pgm str sep n splits str by sep n times | ||
151 | */ | ||
152 | int | ||
153 | main(argc, argv) | ||
154 | int argc; | ||
155 | char *argv[]; | ||
156 | { | ||
157 | char buf[512]; | ||
158 | register int n; | ||
159 | # define MNF 10 | ||
160 | char *fields[MNF]; | ||
161 | |||
162 | if (argc > 4) | ||
163 | for (n = atoi(argv[3]); n > 0; n--) { | ||
164 | (void) strcpy(buf, argv[1]); | ||
165 | } | ||
166 | else if (argc > 3) | ||
167 | for (n = atoi(argv[3]); n > 0; n--) { | ||
168 | (void) strcpy(buf, argv[1]); | ||
169 | (void) split(buf, fields, MNF, argv[2]); | ||
170 | } | ||
171 | else if (argc > 2) | ||
172 | dosplit(argv[1], argv[2]); | ||
173 | else if (argc > 1) | ||
174 | while (fgets(buf, sizeof(buf), stdin) != NULL) { | ||
175 | buf[strlen(buf)-1] = '\0'; /* stomp newline */ | ||
176 | dosplit(buf, argv[1]); | ||
177 | } | ||
178 | else | ||
179 | regress(); | ||
180 | |||
181 | exit(0); | ||
182 | } | ||
183 | |||
184 | dosplit(string, seps) | ||
185 | char *string; | ||
186 | char *seps; | ||
187 | { | ||
188 | # define NF 5 | ||
189 | char *fields[NF]; | ||
190 | register int nf; | ||
191 | |||
192 | nf = split(string, fields, NF, seps); | ||
193 | print(nf, NF, fields); | ||
194 | } | ||
195 | |||
196 | print(nf, nfp, fields) | ||
197 | int nf; | ||
198 | int nfp; | ||
199 | char *fields[]; | ||
200 | { | ||
201 | register int fn; | ||
202 | register int bound; | ||
203 | |||
204 | bound = (nf > nfp) ? nfp : nf; | ||
205 | printf("%d:\t", nf); | ||
206 | for (fn = 0; fn < bound; fn++) | ||
207 | printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n"); | ||
208 | } | ||
209 | |||
210 | #define RNF 5 /* some table entries know this */ | ||
211 | struct { | ||
212 | char *str; | ||
213 | char *seps; | ||
214 | int nf; | ||
215 | char *fi[RNF]; | ||
216 | } tests[] = { | ||
217 | "", " ", 0, { "" }, | ||
218 | " ", " ", 2, { "", "" }, | ||
219 | "x", " ", 1, { "x" }, | ||
220 | "xy", " ", 1, { "xy" }, | ||
221 | "x y", " ", 2, { "x", "y" }, | ||
222 | "abc def g ", " ", 5, { "abc", "def", "", "g", "" }, | ||
223 | " a bcd", " ", 4, { "", "", "a", "bcd" }, | ||
224 | "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, | ||
225 | " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, | ||
226 | |||
227 | "", " _", 0, { "" }, | ||
228 | " ", " _", 2, { "", "" }, | ||
229 | "x", " _", 1, { "x" }, | ||
230 | "x y", " _", 2, { "x", "y" }, | ||
231 | "ab _ cd", " _", 2, { "ab", "cd" }, | ||
232 | " a_b c ", " _", 5, { "", "a", "b", "c", "" }, | ||
233 | "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" }, | ||
234 | " a b c d ", " _", 6, { "", "a", "b", "c", "d " }, | ||
235 | |||
236 | "", " _~", 0, { "" }, | ||
237 | " ", " _~", 2, { "", "" }, | ||
238 | "x", " _~", 1, { "x" }, | ||
239 | "x y", " _~", 2, { "x", "y" }, | ||
240 | "ab _~ cd", " _~", 2, { "ab", "cd" }, | ||
241 | " a_b c~", " _~", 5, { "", "a", "b", "c", "" }, | ||
242 | "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" }, | ||
243 | "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " }, | ||
244 | |||
245 | "", " _~-", 0, { "" }, | ||
246 | " ", " _~-", 2, { "", "" }, | ||
247 | "x", " _~-", 1, { "x" }, | ||
248 | "x y", " _~-", 2, { "x", "y" }, | ||
249 | "ab _~- cd", " _~-", 2, { "ab", "cd" }, | ||
250 | " a_b c~", " _~-", 5, { "", "a", "b", "c", "" }, | ||
251 | "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" }, | ||
252 | "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " }, | ||
253 | |||
254 | "", " ", 0, { "" }, | ||
255 | " ", " ", 2, { "", "" }, | ||
256 | "x", " ", 1, { "x" }, | ||
257 | "xy", " ", 1, { "xy" }, | ||
258 | "x y", " ", 2, { "x", "y" }, | ||
259 | "abc def g ", " ", 4, { "abc", "def", "g", "" }, | ||
260 | " a bcd", " ", 3, { "", "a", "bcd" }, | ||
261 | "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, | ||
262 | " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, | ||
263 | |||
264 | "", "", 0, { "" }, | ||
265 | " ", "", 0, { "" }, | ||
266 | "x", "", 1, { "x" }, | ||
267 | "xy", "", 1, { "xy" }, | ||
268 | "x y", "", 2, { "x", "y" }, | ||
269 | "abc def g ", "", 3, { "abc", "def", "g" }, | ||
270 | "\t a bcd", "", 2, { "a", "bcd" }, | ||
271 | " a \tb\t c ", "", 3, { "a", "b", "c" }, | ||
272 | "a b c d e ", "", 5, { "a", "b", "c", "d", "e" }, | ||
273 | "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" }, | ||
274 | " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " }, | ||
275 | |||
276 | NULL, NULL, 0, { NULL }, | ||
277 | }; | ||
278 | |||
279 | regress() | ||
280 | { | ||
281 | char buf[512]; | ||
282 | register int n; | ||
283 | char *fields[RNF+1]; | ||
284 | register int nf; | ||
285 | register int i; | ||
286 | register int printit; | ||
287 | register char *f; | ||
288 | |||
289 | for (n = 0; tests[n].str != NULL; n++) { | ||
290 | (void) strcpy(buf, tests[n].str); | ||
291 | fields[RNF] = NULL; | ||
292 | nf = split(buf, fields, RNF, tests[n].seps); | ||
293 | printit = 0; | ||
294 | if (nf != tests[n].nf) { | ||
295 | printf("split `%s' by `%s' gave %d fields, not %d\n", | ||
296 | tests[n].str, tests[n].seps, nf, tests[n].nf); | ||
297 | printit = 1; | ||
298 | } else if (fields[RNF] != NULL) { | ||
299 | printf("split() went beyond array end\n"); | ||
300 | printit = 1; | ||
301 | } else { | ||
302 | for (i = 0; i < nf && i < RNF; i++) { | ||
303 | f = fields[i]; | ||
304 | if (f == NULL) | ||
305 | f = "(NULL)"; | ||
306 | if (strcmp(f, tests[n].fi[i]) != 0) { | ||
307 | printf("split `%s' by `%s', field %d is `%s', not `%s'\n", | ||
308 | tests[n].str, tests[n].seps, | ||
309 | i, fields[i], tests[n].fi[i]); | ||
310 | printit = 1; | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | if (printit) | ||
315 | print(nf, RNF, fields); | ||
316 | } | ||
317 | } | ||
318 | #endif | ||