6 _CONST
char *it
= "<UNSET>"; /* Routine name for message routines. */
9 /* Complain if condition is not true. */
10 #define check(thing) checkit(thing, __LINE__)
13 _DEFUN(checkit
,(ok
,l
),
23 printf("string.c:%d %s\n", l
, it
);
30 /* Complain if first two args don't strcmp as equal. */
31 #define equal(a, b) funcqual(a,b,__LINE__);
34 _DEFUN(funcqual
,(a
,b
,l
),
42 if (a
== NULL
&& b
== NULL
) return;
44 printf("string.c:%d (%s)\n", l
, it
);
56 /* Test strcmp first because we use it to test other things. */
58 check(strcmp("", "") == 0); /* Trivial case. */
59 check(strcmp("a", "a") == 0); /* Identity. */
60 check(strcmp("abc", "abc") == 0); /* Multicharacter. */
61 check(strcmp("abc", "abcd") < 0); /* Length mismatches. */
62 check(strcmp("abcd", "abc") > 0);
63 check(strcmp("abcd", "abce") < 0); /* Honest miscompares. */
64 check(strcmp("abce", "abcd") > 0);
65 check(strcmp("a\103", "a") > 0); /* Tricky if char signed. */
66 check(strcmp("a\103", "a\003") > 0);
68 /* Test strcpy next because we need it to set up other tests. */
70 check(strcpy(one
, "abcd") == one
); /* Returned value. */
71 equal(one
, "abcd"); /* Basic test. */
73 (void) strcpy(one
, "x");
74 equal(one
, "x"); /* Writeover. */
75 equal(one
+2, "cd"); /* Wrote too much? */
77 (void) strcpy(two
, "hi there");
78 (void) strcpy(one
, two
);
79 equal(one
, "hi there"); /* Basic test encore. */
80 equal(two
, "hi there"); /* Stomped on source? */
82 (void) strcpy(one
, "");
83 equal(one
, ""); /* Boundary condition. */
87 (void) strcpy(one
, "ijk");
88 check(strcat(one
, "lmn") == one
); /* Returned value. */
89 equal(one
, "ijklmn"); /* Basic test. */
91 (void) strcpy(one
, "x");
92 (void) strcat(one
, "yz");
93 equal(one
, "xyz"); /* Writeover. */
94 equal(one
+4, "mn"); /* Wrote too much? */
96 (void) strcpy(one
, "gh");
97 (void) strcpy(two
, "ef");
98 (void) strcat(one
, two
);
99 equal(one
, "ghef"); /* Basic test encore. */
100 equal(two
, "ef"); /* Stomped on source? */
102 (void) strcpy(one
, "");
103 (void) strcat(one
, "");
104 equal(one
, ""); /* Boundary conditions. */
105 (void) strcpy(one
, "ab");
106 (void) strcat(one
, "");
108 (void) strcpy(one
, "");
109 (void) strcat(one
, "cd");
112 /* strncat - first test it as strcat, with big counts,
113 then test the count mechanism. */
115 (void) strcpy(one
, "ijk");
116 check(strncat(one
, "lmn", 99) == one
); /* Returned value. */
117 equal(one
, "ijklmn"); /* Basic test. */
119 (void) strcpy(one
, "x");
120 (void) strncat(one
, "yz", 99);
121 equal(one
, "xyz"); /* Writeover. */
122 equal(one
+4, "mn"); /* Wrote too much? */
124 (void) strcpy(one
, "gh");
125 (void) strcpy(two
, "ef");
126 (void) strncat(one
, two
, 99);
127 equal(one
, "ghef"); /* Basic test encore. */
128 equal(two
, "ef"); /* Stomped on source? */
130 (void) strcpy(one
, "");
131 (void) strncat(one
, "", 99);
132 equal(one
, ""); /* Boundary conditions. */
133 (void) strcpy(one
, "ab");
134 (void) strncat(one
, "", 99);
136 (void) strcpy(one
, "");
137 (void) strncat(one
, "cd", 99);
140 (void) strcpy(one
, "ab");
141 (void) strncat(one
, "cdef", 2);
142 equal(one
, "abcd"); /* Count-limited. */
144 (void) strncat(one
, "gh", 0);
145 equal(one
, "abcd"); /* Zero count. */
147 (void) strncat(one
, "gh", 2);
148 equal(one
, "abcdgh"); /* Count _AND length equal. */
150 /* strncmp - first test as strcmp with big counts";*/
151 check(strncmp("", "", 99) == 0); /* Trivial case. */
152 check(strncmp("a", "a", 99) == 0); /* Identity. */
153 check(strncmp("abc", "abc", 99) == 0); /* Multicharacter. */
154 check(strncmp("abc", "abcd", 99) < 0); /* Length unequal. */
155 check(strncmp("abcd", "abc",99) > 0);
156 check(strncmp("abcd", "abce", 99) < 0); /* Honestly unequal. */
157 check(strncmp("abce", "abcd",99)>0);
158 check(strncmp("abce", "abcd", 3) == 0); /* Count limited. */
159 check(strncmp("abce", "abc", 3) == 0); /* Count == length. */
160 check(strncmp("abcd", "abce", 4) < 0); /* Nudging limit. */
161 check(strncmp("abc", "def", 0) == 0); /* Zero count. */
163 /* strncpy - testing is a bit different because of odd semantics. */
165 check(strncpy(one
, "abc", 4) == one
); /* Returned value. */
166 equal(one
, "abc"); /* Did the copy go right? */
168 (void) strcpy(one
, "abcdefgh");
169 (void) strncpy(one
, "xyz", 2);
170 equal(one
, "xycdefgh"); /* Copy cut by count. */
172 (void) strcpy(one
, "abcdefgh");
173 (void) strncpy(one
, "xyz", 3); /* Copy cut just before NUL. */
174 equal(one
, "xyzdefgh");
176 (void) strcpy(one
, "abcdefgh");
177 (void) strncpy(one
, "xyz", 4); /* Copy just includes NUL. */
179 equal(one
+4, "efgh"); /* Wrote too much? */
181 (void) strcpy(one
, "abcdefgh");
182 (void) strncpy(one
, "xyz", 5); /* Copy includes padding. */
187 (void) strcpy(one
, "abc");
188 (void) strncpy(one
, "xyz", 0); /* Zero-length copy. */
191 (void) strncpy(one
, "", 2); /* Zero-length source. */
196 (void) strcpy(one
, "hi there");
197 (void) strncpy(two
, one
, 9);
198 equal(two
, "hi there"); /* Just paranoia. */
199 equal(one
, "hi there"); /* Stomped on source? */
203 check(strlen("") == 0); /* Empty. */
204 check(strlen("a") == 1); /* Single char. */
205 check(strlen("abcd") == 4); /* Multiple chars. */
209 check(strchr("abcd", 'z') == NULL
); /* Not found. */
210 (void) strcpy(one
, "abcd");
211 check(strchr(one
, 'c') == one
+2); /* Basic test. */
212 check(strchr(one
, 'd') == one
+3); /* End of string. */
213 check(strchr(one
, 'a') == one
); /* Beginning. */
214 check(strchr(one
, '\0') == one
+4); /* Finding NUL. */
215 (void) strcpy(one
, "ababa");
216 check(strchr(one
, 'b') == one
+1); /* Finding first. */
217 (void) strcpy(one
, "");
218 check(strchr(one
, 'b') == NULL
); /* Empty string. */
219 check(strchr(one
, '\0') == one
); /* NUL in empty string. */
221 /* index - just like strchr. */
223 check(index("abcd", 'z') == NULL
); /* Not found. */
224 (void) strcpy(one
, "abcd");
225 check(index(one
, 'c') == one
+2); /* Basic test. */
226 check(index(one
, 'd') == one
+3); /* End of string. */
227 check(index(one
, 'a') == one
); /* Beginning. */
228 check(index(one
, '\0') == one
+4); /* Finding NUL. */
229 (void) strcpy(one
, "ababa");
230 check(index(one
, 'b') == one
+1); /* Finding first. */
231 (void) strcpy(one
, "");
232 check(index(one
, 'b') == NULL
); /* Empty string. */
233 check(index(one
, '\0') == one
); /* NUL in empty string. */
237 check(strrchr("abcd", 'z') == NULL
); /* Not found. */
238 (void) strcpy(one
, "abcd");
239 check(strrchr(one
, 'c') == one
+2); /* Basic test. */
240 check(strrchr(one
, 'd') == one
+3); /* End of string. */
241 check(strrchr(one
, 'a') == one
); /* Beginning. */
242 check(strrchr(one
, '\0') == one
+4); /* Finding NUL. */
243 (void) strcpy(one
, "ababa");
244 check(strrchr(one
, 'b') == one
+3); /* Finding last. */
245 (void) strcpy(one
, "");
246 check(strrchr(one
, 'b') == NULL
); /* Empty string. */
247 check(strrchr(one
, '\0') == one
); /* NUL in empty string. */
249 /* rindex - just like strrchr. */
251 check(rindex("abcd", 'z') == NULL
); /* Not found. */
252 (void) strcpy(one
, "abcd");
253 check(rindex(one
, 'c') == one
+2); /* Basic test. */
254 check(rindex(one
, 'd') == one
+3); /* End of string. */
255 check(rindex(one
, 'a') == one
); /* Beginning. */
256 check(rindex(one
, '\0') == one
+4); /* Finding NUL. */
257 (void) strcpy(one
, "ababa");
258 check(rindex(one
, 'b') == one
+3); /* Finding last. */
259 (void) strcpy(one
, "");
260 check(rindex(one
, 'b') == NULL
); /* Empty string. */
261 check(rindex(one
, '\0') == one
); /* NUL in empty string. */
263 /* strpbrk - somewhat like strchr. */
265 check(strpbrk("abcd", "z") == NULL
); /* Not found. */
266 (void) strcpy(one
, "abcd");
267 check(strpbrk(one
, "c") == one
+2); /* Basic test. */
268 check(strpbrk(one
, "d") == one
+3); /* End of string. */
269 check(strpbrk(one
, "a") == one
); /* Beginning. */
270 check(strpbrk(one
, "") == NULL
); /* Empty search list. */
271 check(strpbrk(one
, "cb") == one
+1); /* Multiple search. */
272 (void) strcpy(one
, "abcabdea");
273 check(strpbrk(one
, "b") == one
+1); /* Finding first. */
274 check(strpbrk(one
, "cb") == one
+1); /* With multiple search. */
275 check(strpbrk(one
, "db") == one
+1); /* Another variant. */
276 (void) strcpy(one
, "");
277 check(strpbrk(one
, "bc") == NULL
); /* Empty string. */
278 check(strpbrk(one
, "") == NULL
); /* Both strings empty. */
280 /* strstr - somewhat like strchr. */
282 check(strstr("z", "abcd") == NULL
); /* Not found. */
283 check(strstr("abx", "abcd") == NULL
); /* Dead end. */
284 (void) strcpy(one
, "abcd");
285 check(strstr(one
,"c") == one
+2); /* Basic test. */
286 check(strstr(one
, "bc") == one
+1); /* Multichar. */
287 check(strstr(one
,"d") == one
+3); /* End of string. */
288 check(strstr(one
,"cd") == one
+2); /* Tail of string. */
289 check(strstr(one
,"abc") == one
); /* Beginning. */
290 check(strstr(one
,"abcd") == one
); /* Exact match. */
291 check(strstr(one
,"de") == NULL
); /* Past end. */
292 check(strstr(one
,"") == one
); /* Finding empty. */
293 (void) strcpy(one
, "ababa");
294 check(strstr(one
,"ba") == one
+1); /* Finding first. */
295 (void) strcpy(one
, "");
296 check(strstr(one
, "b") == NULL
); /* Empty string. */
297 check(strstr(one
,"") == one
); /* Empty in empty string. */
298 (void) strcpy(one
, "bcbca");
299 check(strstr(one
,"bca") == one
+2); /* False start. */
300 (void) strcpy(one
, "bbbcabbca");
301 check(strstr(one
,"bbca") == one
+1); /* With overlap. */
305 check(strspn("abcba", "abc") == 5); /* Whole string. */
306 check(strspn("abcba", "ab") == 2); /* Partial. */
307 check(strspn("abc", "qx") == 0); /* None. */
308 check(strspn("", "ab") == 0); /* Null string. */
309 check(strspn("abc", "") == 0); /* Null search list. */
313 check(strcspn("abcba", "qx") == 5); /* Whole string. */
314 check(strcspn("abcba", "cx") == 2); /* Partial. */
315 check(strcspn("abc", "abc") == 0); /* None. */
316 check(strcspn("", "ab") == 0); /* Null string. */
317 check(strcspn("abc", "") == 3); /* Null search list. */
319 /* strtok - the hard one. */
321 (void) strcpy(one
, "first, second, third");
322 equal(strtok(one
, ", "), "first"); /* Basic test. */
324 equal(strtok((char *)NULL
, ", "), "second");
325 equal(strtok((char *)NULL
, ", "), "third");
326 check(strtok((char *)NULL
, ", ") == NULL
);
327 (void) strcpy(one
, ", first, ");
328 equal(strtok(one
, ", "), "first"); /* Extra delims, 1 tok. */
329 check(strtok((char *)NULL
, ", ") == NULL
);
330 (void) strcpy(one
, "1a, 1b; 2a, 2b");
331 equal(strtok(one
, ", "), "1a"); /* Changing delim lists. */
332 equal(strtok((char *)NULL
, "; "), "1b");
333 equal(strtok((char *)NULL
, ", "), "2a");
334 (void) strcpy(two
, "x-y");
335 equal(strtok(two
, "-"), "x"); /* New string before done. */
336 equal(strtok((char *)NULL
, "-"), "y");
337 check(strtok((char *)NULL
, "-") == NULL
);
338 (void) strcpy(one
, "a,b, c,, ,d");
339 equal(strtok(one
, ", "), "a"); /* Different separators. */
340 equal(strtok((char *)NULL
, ", "), "b");
341 equal(strtok((char *)NULL
, " ,"), "c"); /* Permute list too. */
342 equal(strtok((char *)NULL
, " ,"), "d");
343 check(strtok((char *)NULL
, ", ") == NULL
);
344 check(strtok((char *)NULL
, ", ") == NULL
); /* Persistence. */
345 (void) strcpy(one
, ", ");
346 check(strtok(one
, ", ") == NULL
); /* No tokens. */
347 (void) strcpy(one
, "");
348 check(strtok(one
, ", ") == NULL
); /* Empty string. */
349 (void) strcpy(one
, "abc");
350 equal(strtok(one
, ", "), "abc"); /* No delimiters. */
351 check(strtok((char *)NULL
, ", ") == NULL
);
352 (void) strcpy(one
, "abc");
353 equal(strtok(one
, ""), "abc"); /* Empty delimiter list. */
354 check(strtok((char *)NULL
, "") == NULL
);
355 (void) strcpy(one
, "abcdefgh");
356 (void) strcpy(one
, "a,b,c");
357 equal(strtok(one
, ","), "a"); /* Basics again... */
358 equal(strtok((char *)NULL
, ","), "b");
359 equal(strtok((char *)NULL
, ","), "c");
360 check(strtok((char *)NULL
, ",") == NULL
);
361 equal(one
+6, "gh"); /* Stomped past end? */
362 equal(one
, "a"); /* Stomped old tokens? */
368 check(memcmp("a", "a", 1) == 0); /* Identity. */
369 check(memcmp("abc", "abc", 3) == 0); /* Multicharacter. */
370 check(memcmp("abcd", "abce", 4) < 0); /* Honestly unequal. */
371 check(memcmp("abce", "abcd",4));
372 check(memcmp("alph", "beta", 4) < 0);
373 check(memcmp("abce", "abcd", 3) == 0); /* Count limited. */
374 check(memcmp("abc", "def", 0) == 0); /* Zero count. */
376 /* memcmp should test strings as unsigned */
379 check(memcmp(one
, two
,1) > 0);
384 check(memchr("abcd", 'z', 4) == NULL
); /* Not found. */
385 (void) strcpy(one
, "abcd");
386 check(memchr(one
, 'c', 4) == one
+2); /* Basic test. */
387 check(memchr(one
, 'd', 4) == one
+3); /* End of string. */
388 check(memchr(one
, 'a', 4) == one
); /* Beginning. */
389 check(memchr(one
, '\0', 5) == one
+4); /* Finding NUL. */
390 (void) strcpy(one
, "ababa");
391 check(memchr(one
, 'b', 5) == one
+1); /* Finding first. */
392 check(memchr(one
, 'b', 0) == NULL
); /* Zero count. */
393 check(memchr(one
, 'a', 1) == one
); /* Singleton case. */
394 (void) strcpy(one
, "a\203b");
395 check(memchr(one
, 0203, 3) == one
+1); /* Unsignedness. */
397 /* memcpy - need not work for overlap. */
399 check(memcpy(one
, "abc", 4) == one
); /* Returned value. */
400 equal(one
, "abc"); /* Did the copy go right? */
402 (void) strcpy(one
, "abcdefgh");
403 (void) memcpy(one
+1, "xyz", 2);
404 equal(one
, "axydefgh"); /* Basic test. */
406 (void) strcpy(one
, "abc");
407 (void) memcpy(one
, "xyz", 0);
408 equal(one
, "abc"); /* Zero-length copy. */
410 (void) strcpy(one
, "hi there");
411 (void) strcpy(two
, "foo");
412 (void) memcpy(two
, one
, 9);
413 equal(two
, "hi there"); /* Just paranoia. */
414 equal(one
, "hi there"); /* Stomped on source? */
416 /* memmove - must work on overlap. */
418 check(memmove(one
, "abc", 4) == one
); /* Returned value. */
419 equal(one
, "abc"); /* Did the copy go right? */
421 (void) strcpy(one
, "abcdefgh");
422 (void) memmove(one
+1, "xyz", 2);
423 equal(one
, "axydefgh"); /* Basic test. */
425 (void) strcpy(one
, "abc");
426 (void) memmove(one
, "xyz", 0);
427 equal(one
, "abc"); /* Zero-length copy. */
429 (void) strcpy(one
, "hi there");
430 (void) strcpy(two
, "foo");
431 (void) memmove(two
, one
, 9);
432 equal(two
, "hi there"); /* Just paranoia. */
433 equal(one
, "hi there"); /* Stomped on source? */
435 (void) strcpy(one
, "abcdefgh");
436 (void) memmove(one
+1, one
, 9);
437 equal(one
, "aabcdefgh"); /* Overlap, right-to-left. */
439 (void) strcpy(one
, "abcdefgh");
440 (void) memmove(one
+1, one
+2, 7);
441 equal(one
, "acdefgh"); /* Overlap, left-to-right. */
443 (void) strcpy(one
, "abcdefgh");
444 (void) memmove(one
, one
, 9);
445 equal(one
, "abcdefgh"); /* 100% overlap. */
448 /* memccpy - first test like memcpy, then the search part
449 The SVID, the only place where memccpy is mentioned, says
450 overlap might fail, so we don't try it. Besides, it's hard
451 to see the rationale for a non-left-to-right memccpy. */
453 check(memccpy(one
, "abc", 'q', 4) == NULL
); /* Returned value. */
454 equal(one
, "abc"); /* Did the copy go right? */
456 (void) strcpy(one
, "abcdefgh");
457 (void) memccpy(one
+1, "xyz", 'q', 2);
458 equal(one
, "axydefgh"); /* Basic test. */
460 (void) strcpy(one
, "abc");
461 (void) memccpy(one
, "xyz", 'q', 0);
462 equal(one
, "abc"); /* Zero-length copy. */
464 (void) strcpy(one
, "hi there");
465 (void) strcpy(two
, "foo");
466 (void) memccpy(two
, one
, 'q', 9);
467 equal(two
, "hi there"); /* Just paranoia. */
468 equal(one
, "hi there"); /* Stomped on source? */
470 (void) strcpy(one
, "abcdefgh");
471 (void) strcpy(two
, "horsefeathers");
472 check(memccpy(two
, one
, 'f', 9) == two
+6); /* Returned value. */
473 equal(one
, "abcdefgh"); /* Source intact? */
474 equal(two
, "abcdefeathers"); /* Copy correct? */
476 (void) strcpy(one
, "abcd");
477 (void) strcpy(two
, "bumblebee");
478 check(memccpy(two
, one
, 'a', 4) == two
+1); /* First char. */
479 equal(two
, "aumblebee");
480 check(memccpy(two
, one
, 'd', 4) == two
+4); /* Last char. */
481 equal(two
, "abcdlebee");
482 (void) strcpy(one
, "xyz");
483 check(memccpy(two
, one
, 'x', 1) == two
+1); /* Singleton. */
484 equal(two
, "xbcdlebee");
488 (void) strcpy(one
, "abcdefgh");
489 check(memset(one
+1, 'x', 3) == one
+1); /* Return value. */
490 equal(one
, "axxxefgh"); /* Basic test. */
492 (void) memset(one
+2, 'y', 0);
493 equal(one
, "axxxefgh"); /* Zero-length set. */
495 (void) memset(one
+5, 0, 1);
496 equal(one
, "axxxe"); /* Zero fill. */
497 equal(one
+6, "gh"); /* _AND the leftover. */
499 (void) memset(one
+2, 010045, 1);
500 equal(one
, "ax\045xe"); /* Unsigned char convert. */
502 /* bcopy - much like memcpy.
503 Berklix manual is silent about overlap, so don't test it. */
505 (void) bcopy("abc", one
, 4);
506 equal(one
, "abc"); /* Simple copy. */
508 (void) strcpy(one
, "abcdefgh");
509 (void) bcopy("xyz", one
+1, 2);
510 equal(one
, "axydefgh"); /* Basic test. */
512 (void) strcpy(one
, "abc");
513 (void) bcopy("xyz", one
, 0);
514 equal(one
, "abc"); /* Zero-length copy. */
516 (void) strcpy(one
, "hi there");
517 (void) strcpy(two
, "foo");
518 (void) bcopy(one
, two
, 9);
519 equal(two
, "hi there"); /* Just paranoia. */
520 equal(one
, "hi there"); /* Stomped on source? */
524 (void) strcpy(one
, "abcdef");
526 equal(one
, "ab"); /* Basic test. */
530 (void) strcpy(one
, "abcdef");
532 equal(one
, "abcdef"); /* Zero-length copy. */
534 /* bcmp - somewhat like memcmp. */
536 check(bcmp("a", "a", 1) == 0); /* Identity. */
537 check(bcmp("abc", "abc", 3) == 0); /* Multicharacter. */
538 check(bcmp("abcd", "abce", 4) != 0); /* Honestly unequal. */
539 check(bcmp("abce", "abcd",4));
540 check(bcmp("alph", "beta", 4) != 0);
541 check(bcmp("abce", "abcd", 3) == 0); /* Count limited. */
542 check(bcmp("abc", "def", 0) == 0); /* Zero count. */
544 #if 0 /* strerror - VERY system-dependent. */
546 extern CONST
unsigned int _sys_nerr
;
547 extern CONST
char *CONST _sys_errlist
[];
550 f
= open("/", O_WRONLY
); /* Should always fail. */
551 check(f
< 0 && errno
> 0 && errno
< _sys_nerr
);
552 equal(strerror(errno
), _sys_errlist
[errno
]);