(test_main): Use negative byte value is test.
[kopensolaris-gnu/glibc.git] / string / tester.c
1 /* Tester for string functions.
2    Copyright (C) 1995-2000, 2001, 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23
24 /* Make sure we don't test the optimized inline functions if we want to
25    test the real implementation.  */
26 #if !defined DO_STRING_INLINES
27 #undef __USE_STRING_INLINES
28 #endif
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <fcntl.h>
36
37 #ifndef HAVE_GNU_LD
38 #define _sys_nerr       sys_nerr
39 #define _sys_errlist    sys_errlist
40 #endif
41
42 #define STREQ(a, b)     (strcmp((a), (b)) == 0)
43
44 const char *it = "<UNSET>";     /* Routine name for message routines. */
45 size_t errors = 0;
46
47 /* Complain if condition is not true.  */
48 static void
49 check (int thing, int number)
50 {
51   if (!thing)
52     {
53       printf("%s flunked test %d\n", it, number);
54       ++errors;
55     }
56 }
57
58 /* Complain if first two args don't strcmp as equal.  */
59 static void
60 equal (const char *a, const char *b, int number)
61 {
62   check(a != NULL && b != NULL && STREQ (a, b), number);
63 }
64
65 char one[50];
66 char two[50];
67 char *cp;
68
69 static void
70 test_strcmp (void)
71 {
72   it = "strcmp";
73   check (strcmp ("", "") == 0, 1);              /* Trivial case. */
74   check (strcmp ("a", "a") == 0, 2);            /* Identity. */
75   check (strcmp ("abc", "abc") == 0, 3);        /* Multicharacter. */
76   check (strcmp ("abc", "abcd") < 0, 4);        /* Length mismatches. */
77   check (strcmp ("abcd", "abc") > 0, 5);
78   check (strcmp ("abcd", "abce") < 0, 6);       /* Honest miscompares. */
79   check (strcmp ("abce", "abcd") > 0, 7);
80   check (strcmp ("a\203", "a") > 0, 8);         /* Tricky if char signed. */
81   check (strcmp ("a\203", "a\003") > 0, 9);
82
83   {
84     char buf1[0x40], buf2[0x40];
85     int i, j;
86     for (i=0; i < 0x10; i++)
87       for (j = 0; j < 0x10; j++)
88         {
89           int k;
90           for (k = 0; k < 0x3f; k++)
91             {
92               buf1[k] = '0' ^ (k & 4);
93               buf2[k] = '4' ^ (k & 4);
94             }
95           buf1[i] = buf1[0x3f] = 0;
96           buf2[j] = buf2[0x3f] = 0;
97           for (k = 0; k < 0xf; k++)
98             {
99               int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
100               check (strcmp (buf1+i,buf2+j) == 0, cnum);
101               buf1[i+k] = 'A' + i + k;
102               buf1[i+k+1] = 0;
103               check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
104               check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
105               buf2[j+k] = 'B' + i + k;
106               buf2[j+k+1] = 0;
107               check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
108               check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
109               buf2[j+k] = 'A' + i + k;
110               buf1[i] = 'A' + i + 0x80;
111               check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
112               check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
113               buf1[i] = 'A' + i;
114             }
115         }
116   }
117 }
118
119 #define SIMPLE_COPY(fn, n, str, ntest) \
120   do {                                                                        \
121     int __n;                                                                  \
122     char *cp;                                                                 \
123     for (__n = 0; __n < (int) sizeof (one); ++__n)                            \
124       one[__n] = 'Z';                                                         \
125     fn (one, str);                                                            \
126     for (cp = one, __n = 0; __n < n; ++__n, ++cp)                             \
127       check (*cp == '0' + (n % 10), ntest);                                   \
128     check (*cp == '\0', ntest);                                               \
129   } while (0)
130
131 static void
132 test_strcpy (void)
133 {
134   int i;
135   it = "strcpy";
136   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
137   equal (one, "abcd", 2);               /* Basic test. */
138
139   (void) strcpy (one, "x");
140   equal (one, "x", 3);                  /* Writeover. */
141   equal (one+2, "cd", 4);               /* Wrote too much? */
142
143   (void) strcpy (two, "hi there");
144   (void) strcpy (one, two);
145   equal (one, "hi there", 5);           /* Basic test encore. */
146   equal (two, "hi there", 6);           /* Stomped on source? */
147
148   (void) strcpy (one, "");
149   equal (one, "", 7);                   /* Boundary condition. */
150
151   for (i = 0; i < 16; i++)
152     {
153       (void) strcpy (one + i, "hi there");      /* Unaligned destination. */
154       equal (one + i, "hi there", 8 + (i * 2));
155       (void) strcpy (two, one + i);             /* Unaligned source. */
156       equal (two, "hi there", 9 + (i * 2));
157     }
158
159   SIMPLE_COPY(strcpy, 0, "", 41);
160   SIMPLE_COPY(strcpy, 1, "1", 42);
161   SIMPLE_COPY(strcpy, 2, "22", 43);
162   SIMPLE_COPY(strcpy, 3, "333", 44);
163   SIMPLE_COPY(strcpy, 4, "4444", 45);
164   SIMPLE_COPY(strcpy, 5, "55555", 46);
165   SIMPLE_COPY(strcpy, 6, "666666", 47);
166   SIMPLE_COPY(strcpy, 7, "7777777", 48);
167   SIMPLE_COPY(strcpy, 8, "88888888", 49);
168   SIMPLE_COPY(strcpy, 9, "999999999", 50);
169   SIMPLE_COPY(strcpy, 10, "0000000000", 51);
170   SIMPLE_COPY(strcpy, 11, "11111111111", 52);
171   SIMPLE_COPY(strcpy, 12, "222222222222", 53);
172   SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
173   SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
174   SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
175   SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
176
177   /* Simple test using implicitly coerced `void *' arguments.  */
178   const void *src = "frobozz";
179   void *dst = one;
180   check (strcpy (dst, src) == dst, 1);
181   equal (dst, "frobozz", 2);
182 }
183
184 static void
185 test_stpcpy (void)
186 {
187   it = "stpcpy";
188   check ((stpcpy (one, "a") - one) == 1, 1);
189   equal (one, "a", 2);
190
191   check ((stpcpy (one, "ab") - one) == 2, 3);
192   equal (one, "ab", 4);
193
194   check ((stpcpy (one, "abc") - one) == 3, 5);
195   equal (one, "abc", 6);
196
197   check ((stpcpy (one, "abcd") - one) == 4, 7);
198   equal (one, "abcd", 8);
199
200   check ((stpcpy (one, "abcde") - one) == 5, 9);
201   equal (one, "abcde", 10);
202
203   check ((stpcpy (one, "abcdef") - one) == 6, 11);
204   equal (one, "abcdef", 12);
205
206   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
207   equal (one, "abcdefg", 14);
208
209   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
210   equal (one, "abcdefgh", 16);
211
212   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
213   equal (one, "abcdefghi", 18);
214
215   check ((stpcpy (one, "x") - one) == 1, 19);
216   equal (one, "x", 20);                 /* Writeover. */
217   equal (one+2, "cdefghi", 21);         /* Wrote too much? */
218
219   check ((stpcpy (one, "xx") - one) == 2, 22);
220   equal (one, "xx", 23);                /* Writeover. */
221   equal (one+3, "defghi", 24);          /* Wrote too much? */
222
223   check ((stpcpy (one, "xxx") - one) == 3, 25);
224   equal (one, "xxx", 26);               /* Writeover. */
225   equal (one+4, "efghi", 27);           /* Wrote too much? */
226
227   check ((stpcpy (one, "xxxx") - one) == 4, 28);
228   equal (one, "xxxx", 29);              /* Writeover. */
229   equal (one+5, "fghi", 30);            /* Wrote too much? */
230
231   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
232   equal (one, "xxxxx", 32);             /* Writeover. */
233   equal (one+6, "ghi", 33);             /* Wrote too much? */
234
235   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
236   equal (one, "xxxxxx", 35);            /* Writeover. */
237   equal (one+7, "hi", 36);              /* Wrote too much? */
238
239   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
240   equal (one, "xxxxxxx", 38);           /* Writeover. */
241   equal (one+8, "i", 39);               /* Wrote too much? */
242
243   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
244   equal (one, "abc", 41);
245   equal (one + 4, "xxx", 42);
246
247   SIMPLE_COPY(stpcpy, 0, "", 43);
248   SIMPLE_COPY(stpcpy, 1, "1", 44);
249   SIMPLE_COPY(stpcpy, 2, "22", 45);
250   SIMPLE_COPY(stpcpy, 3, "333", 46);
251   SIMPLE_COPY(stpcpy, 4, "4444", 47);
252   SIMPLE_COPY(stpcpy, 5, "55555", 48);
253   SIMPLE_COPY(stpcpy, 6, "666666", 49);
254   SIMPLE_COPY(stpcpy, 7, "7777777", 50);
255   SIMPLE_COPY(stpcpy, 8, "88888888", 51);
256   SIMPLE_COPY(stpcpy, 9, "999999999", 52);
257   SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
258   SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
259   SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
260   SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
261   SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
262   SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
263   SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
264 }
265
266 static void
267 test_stpncpy (void)
268 {
269   it = "stpncpy";
270   memset (one, 'x', sizeof (one));
271   check (stpncpy (one, "abc", 2) == one + 2, 1);
272   check (stpncpy (one, "abc", 3) == one + 3, 2);
273   check (stpncpy (one, "abc", 4) == one + 3, 3);
274   check (one[3] == '\0' && one[4] == 'x', 4);
275   check (stpncpy (one, "abcd", 5) == one + 4, 5);
276   check (one[4] == '\0' && one[5] == 'x', 6);
277   check (stpncpy (one, "abcd", 6) == one + 4, 7);
278   check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
279 }
280
281 static void
282 test_strcat (void)
283 {
284   it = "strcat";
285   (void) strcpy (one, "ijk");
286   check (strcat (one, "lmn") == one, 1); /* Returned value. */
287   equal (one, "ijklmn", 2);             /* Basic test. */
288
289   (void) strcpy (one, "x");
290   (void) strcat (one, "yz");
291   equal (one, "xyz", 3);                        /* Writeover. */
292   equal (one+4, "mn", 4);                       /* Wrote too much? */
293
294   (void) strcpy (one, "gh");
295   (void) strcpy (two, "ef");
296   (void) strcat (one, two);
297   equal (one, "ghef", 5);                       /* Basic test encore. */
298   equal (two, "ef", 6);                 /* Stomped on source? */
299
300   (void) strcpy (one, "");
301   (void) strcat (one, "");
302   equal (one, "", 7);                   /* Boundary conditions. */
303   (void) strcpy (one, "ab");
304   (void) strcat (one, "");
305   equal (one, "ab", 8);
306   (void) strcpy (one, "");
307   (void) strcat (one, "cd");
308   equal (one, "cd", 9);
309 }
310
311 static void
312 test_strncat (void)
313 {
314   /* First test it as strcat, with big counts, then test the count
315      mechanism.  */
316   it = "strncat";
317   (void) strcpy (one, "ijk");
318   check (strncat (one, "lmn", 99) == one, 1);   /* Returned value. */
319   equal (one, "ijklmn", 2);             /* Basic test. */
320
321   (void) strcpy (one, "x");
322   (void) strncat (one, "yz", 99);
323   equal (one, "xyz", 3);                /* Writeover. */
324   equal (one+4, "mn", 4);               /* Wrote too much? */
325
326   (void) strcpy (one, "gh");
327   (void) strcpy (two, "ef");
328   (void) strncat (one, two, 99);
329   equal (one, "ghef", 5);                       /* Basic test encore. */
330   equal (two, "ef", 6);                 /* Stomped on source? */
331
332   (void) strcpy (one, "");
333   (void) strncat (one, "", 99);
334   equal (one, "", 7);                   /* Boundary conditions. */
335   (void) strcpy (one, "ab");
336   (void) strncat (one, "", 99);
337   equal (one, "ab", 8);
338   (void) strcpy (one, "");
339   (void) strncat (one, "cd", 99);
340   equal (one, "cd", 9);
341
342   (void) strcpy (one, "ab");
343   (void) strncat (one, "cdef", 2);
344   equal (one, "abcd", 10);                      /* Count-limited. */
345
346   (void) strncat (one, "gh", 0);
347   equal (one, "abcd", 11);                      /* Zero count. */
348
349   (void) strncat (one, "gh", 2);
350   equal (one, "abcdgh", 12);            /* Count and length equal. */
351 }
352
353 static void
354 test_strncmp (void)
355 {
356   /* First test as strcmp with big counts, then test count code.  */
357   it = "strncmp";
358   check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
359   check (strncmp ("a", "a", 99) == 0, 2);       /* Identity. */
360   check (strncmp ("abc", "abc", 99) == 0, 3);   /* Multicharacter. */
361   check (strncmp ("abc", "abcd", 99) < 0, 4);   /* Length unequal. */
362   check (strncmp ("abcd", "abc", 99) > 0, 5);
363   check (strncmp ("abcd", "abce", 99) < 0, 6);  /* Honestly unequal. */
364   check (strncmp ("abce", "abcd", 99) > 0, 7);
365   check (strncmp ("a\203", "a", 2) > 0, 8);     /* Tricky if '\203' < 0 */
366   check (strncmp ("a\203", "a\003", 2) > 0, 9);
367   check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
368   check (strncmp ("abce", "abc", 3) == 0, 11);  /* Count == length. */
369   check (strncmp ("abcd", "abce", 4) < 0, 12);  /* Nudging limit. */
370   check (strncmp ("abc", "def", 0) == 0, 13);   /* Zero count. */
371 }
372
373 static void
374 test_strncpy (void)
375 {
376   /* Testing is a bit different because of odd semantics.  */
377   it = "strncpy";
378   check (strncpy (one, "abc", 4) == one, 1);    /* Returned value. */
379   equal (one, "abc", 2);                        /* Did the copy go right? */
380
381   (void) strcpy (one, "abcdefgh");
382   (void) strncpy (one, "xyz", 2);
383   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
384
385   (void) strcpy (one, "abcdefgh");
386   (void) strncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
387   equal (one, "xyzdefgh", 4);
388
389   (void) strcpy (one, "abcdefgh");
390   (void) strncpy (one, "xyz", 4);               /* Copy just includes NUL. */
391   equal (one, "xyz", 5);
392   equal (one+4, "efgh", 6);                     /* Wrote too much? */
393
394   (void) strcpy (one, "abcdefgh");
395   (void) strncpy (one, "xyz", 5);               /* Copy includes padding. */
396   equal (one, "xyz", 7);
397   equal (one+4, "", 8);
398   equal (one+5, "fgh", 9);
399
400   (void) strcpy (one, "abc");
401   (void) strncpy (one, "xyz", 0);               /* Zero-length copy. */
402   equal (one, "abc", 10);
403
404   (void) strncpy (one, "", 2);          /* Zero-length source. */
405   equal (one, "", 11);
406   equal (one+1, "", 12);
407   equal (one+2, "c", 13);
408
409   (void) strcpy (one, "hi there");
410   (void) strncpy (two, one, 9);
411   equal (two, "hi there", 14);          /* Just paranoia. */
412   equal (one, "hi there", 15);          /* Stomped on source? */
413 }
414
415 static void
416 test_strlen (void)
417 {
418   it = "strlen";
419   check (strlen ("") == 0, 1);          /* Empty. */
420   check (strlen ("a") == 1, 2);         /* Single char. */
421   check (strlen ("abcd") == 4, 3);      /* Multiple chars. */
422   {
423     char buf[4096];
424     int i;
425     char *p;
426     for (i=0; i < 0x100; i++)
427       {
428         p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
429         strcpy (p, "OK");
430         strcpy (p+3, "BAD/WRONG");
431         check (strlen (p) == 2, 4+i);
432       }
433    }
434 }
435
436 static void
437 test_strchr (void)
438 {
439   it = "strchr";
440   check (strchr ("abcd", 'z') == NULL, 1);      /* Not found. */
441   (void) strcpy (one, "abcd");
442   check (strchr (one, 'c') == one+2, 2);        /* Basic test. */
443   check (strchr (one, 'd') == one+3, 3);        /* End of string. */
444   check (strchr (one, 'a') == one, 4);          /* Beginning. */
445   check (strchr (one, '\0') == one+4, 5);       /* Finding NUL. */
446   (void) strcpy (one, "ababa");
447   check (strchr (one, 'b') == one+1, 6);        /* Finding first. */
448   (void) strcpy (one, "");
449   check (strchr (one, 'b') == NULL, 7);         /* Empty string. */
450   check (strchr (one, '\0') == one, 8);         /* NUL in empty string. */
451   {
452     char buf[4096];
453     int i;
454     char *p;
455     for (i=0; i < 0x100; i++)
456       {
457         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
458         strcpy (p, "OK");
459         strcpy (p+3, "BAD/WRONG");
460         check (strchr (p, '/') == NULL, 9+i);
461       }
462    }
463 }
464
465 static void
466 test_strchrnul (void)
467 {
468   const char *os;
469   it = "strchrnul";
470   cp = strchrnul ((os = "abcd"), 'z');
471   check (*cp == '\0', 1);                       /* Not found. */
472   check (cp == os + 4, 2);
473   (void) strcpy (one, "abcd");
474   check (strchrnul (one, 'c') == one+2, 3);     /* Basic test. */
475   check (strchrnul (one, 'd') == one+3, 4);     /* End of string. */
476   check (strchrnul (one, 'a') == one, 5);       /* Beginning. */
477   check (strchrnul (one, '\0') == one+4, 6);    /* Finding NUL. */
478   (void) strcpy (one, "ababa");
479   check (strchrnul (one, 'b') == one+1, 7);     /* Finding first. */
480   (void) strcpy (one, "");
481   check (strchrnul (one, 'b') == one, 8);       /* Empty string. */
482   check (strchrnul (one, '\0') == one, 9);      /* NUL in empty string. */
483   {
484     char buf[4096];
485     int i;
486     char *p;
487     for (i=0; i < 0x100; i++)
488       {
489         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
490         strcpy (p, "OK");
491         strcpy (p+3, "BAD/WRONG");
492         cp = strchrnul (p, '/');
493         check (*cp == '\0', 9+2*i);
494         check (cp == p+2, 10+2*i);
495       }
496    }
497 }
498
499 static void
500 test_rawmemchr (void)
501 {
502   it = "rawmemchr";
503   (void) strcpy (one, "abcd");
504   check (rawmemchr (one, 'c') == one+2, 1);     /* Basic test. */
505   check (rawmemchr (one, 'd') == one+3, 2);     /* End of string. */
506   check (rawmemchr (one, 'a') == one, 3);               /* Beginning. */
507   check (rawmemchr (one, '\0') == one+4, 4);    /* Finding NUL. */
508   (void) strcpy (one, "ababa");
509   check (rawmemchr (one, 'b') == one+1, 5);     /* Finding first. */
510   (void) strcpy (one, "");
511   check (rawmemchr (one, '\0') == one, 6);      /* NUL in empty string. */
512   {
513     char buf[4096];
514     int i;
515     char *p;
516     for (i=0; i < 0x100; i++)
517       {
518         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
519         strcpy (p, "OK");
520         strcpy (p+3, "BAD/WRONG");
521         check (rawmemchr (p, 'R') == p+8, 6+i);
522       }
523    }
524 }
525
526 static void
527 test_index (void)
528 {
529   it = "index";
530   check (index ("abcd", 'z') == NULL, 1);       /* Not found. */
531   (void) strcpy (one, "abcd");
532   check (index (one, 'c') == one+2, 2); /* Basic test. */
533   check (index (one, 'd') == one+3, 3); /* End of string. */
534   check (index (one, 'a') == one, 4);   /* Beginning. */
535   check (index (one, '\0') == one+4, 5);        /* Finding NUL. */
536   (void) strcpy (one, "ababa");
537   check (index (one, 'b') == one+1, 6); /* Finding first. */
538   (void) strcpy (one, "");
539   check (index (one, 'b') == NULL, 7);  /* Empty string. */
540   check (index (one, '\0') == one, 8);  /* NUL in empty string. */
541 }
542
543 static void
544 test_strrchr (void)
545 {
546   it = "strrchr";
547   check (strrchr ("abcd", 'z') == NULL, 1);     /* Not found. */
548   (void) strcpy (one, "abcd");
549   check (strrchr (one, 'c') == one+2, 2);       /* Basic test. */
550   check (strrchr (one, 'd') == one+3, 3);       /* End of string. */
551   check (strrchr (one, 'a') == one, 4);         /* Beginning. */
552   check (strrchr (one, '\0') == one+4, 5);      /* Finding NUL. */
553   (void) strcpy (one, "ababa");
554   check (strrchr (one, 'b') == one+3, 6);       /* Finding last. */
555   (void) strcpy (one, "");
556   check (strrchr (one, 'b') == NULL, 7);        /* Empty string. */
557   check (strrchr (one, '\0') == one, 8);        /* NUL in empty string. */
558   {
559     char buf[4096];
560     int i;
561     char *p;
562     for (i=0; i < 0x100; i++)
563       {
564         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
565         strcpy (p, "OK");
566         strcpy (p+3, "BAD/WRONG");
567         check (strrchr (p, '/') == NULL, 9+i);
568       }
569    }
570 }
571
572 static void
573 test_memrchr (void)
574 {
575   size_t l;
576   it = "memrchr";
577   check (memrchr ("abcd", 'z', 5) == NULL, 1);  /* Not found. */
578   (void) strcpy (one, "abcd");
579   l = strlen (one) + 1;
580   check (memrchr (one, 'c', l) == one+2, 2);    /* Basic test. */
581   check (memrchr (one, 'd', l) == one+3, 3);    /* End of string. */
582   check (memrchr (one, 'a', l) == one, 4);              /* Beginning. */
583   check (memrchr (one, '\0', l) == one+4, 5);   /* Finding NUL. */
584   (void) strcpy (one, "ababa");
585   l = strlen (one) + 1;
586   check (memrchr (one, 'b', l) == one+3, 6);    /* Finding last. */
587   (void) strcpy (one, "");
588   l = strlen (one) + 1;
589   check (memrchr (one, 'b', l) == NULL, 7);     /* Empty string. */
590   check (memrchr (one, '\0', l) == one, 8);     /* NUL in empty string. */
591
592   /* now test all possible alignment and length combinations to catch
593      bugs due to unrolled loops (assuming unrolling is limited to no
594      more than 128 byte chunks: */
595   {
596     char buf[128 + sizeof(long)];
597     long align, len, i, pos;
598
599     for (align = 0; align < (long) sizeof(long); ++align) {
600       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
601         for (i = 0; i < len; ++i)
602           buf[align + i] = 'x';         /* don't depend on memset... */
603
604         for (pos = len - 1; pos >= 0; --pos) {
605 #if 0
606           printf("align %d, len %d, pos %d\n", align, len, pos);
607 #endif
608           check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
609           check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
610                 10);
611           buf[align + pos] = '-';
612         }
613       }
614     }
615   }
616 }
617
618 static void
619 test_rindex (void)
620 {
621   it = "rindex";
622   check (rindex ("abcd", 'z') == NULL, 1);      /* Not found. */
623   (void) strcpy (one, "abcd");
624   check (rindex (one, 'c') == one+2, 2);        /* Basic test. */
625   check (rindex (one, 'd') == one+3, 3);        /* End of string. */
626   check (rindex (one, 'a') == one, 4);  /* Beginning. */
627   check (rindex (one, '\0') == one+4, 5);       /* Finding NUL. */
628   (void) strcpy (one, "ababa");
629   check (rindex (one, 'b') == one+3, 6);        /* Finding last. */
630   (void) strcpy (one, "");
631   check (rindex (one, 'b') == NULL, 7); /* Empty string. */
632   check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
633 }
634
635 static void
636 test_strpbrk (void)
637 {
638   it = "strpbrk";
639   check(strpbrk("abcd", "z") == NULL, 1);       /* Not found. */
640   (void) strcpy(one, "abcd");
641   check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
642   check(strpbrk(one, "d") == one+3, 3); /* End of string. */
643   check(strpbrk(one, "a") == one, 4);   /* Beginning. */
644   check(strpbrk(one, "") == NULL, 5);   /* Empty search list. */
645   check(strpbrk(one, "cb") == one+1, 6);        /* Multiple search. */
646   (void) strcpy(one, "abcabdea");
647   check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
648   check(strpbrk(one, "cb") == one+1, 8);        /* With multiple search. */
649   check(strpbrk(one, "db") == one+1, 9);        /* Another variant. */
650   (void) strcpy(one, "");
651   check(strpbrk(one, "bc") == NULL, 10);        /* Empty string. */
652   (void) strcpy(one, "");
653   check(strpbrk(one, "bcd") == NULL, 11);       /* Empty string. */
654   (void) strcpy(one, "");
655   check(strpbrk(one, "bcde") == NULL, 12);      /* Empty string. */
656   check(strpbrk(one, "") == NULL, 13);  /* Both strings empty. */
657   (void) strcpy(one, "abcabdea");
658   check(strpbrk(one, "befg") == one+1, 14);     /* Finding first. */
659   check(strpbrk(one, "cbr") == one+1, 15);      /* With multiple search. */
660   check(strpbrk(one, "db") == one+1, 16);       /* Another variant. */
661   check(strpbrk(one, "efgh") == one+6, 17);     /* And yet another. */
662 }
663
664 static void
665 test_strstr (void)
666 {
667   it = "strstr";
668   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
669   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
670   (void) strcpy(one, "abcd");
671   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
672   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
673   check(strstr(one, "d") == one+3, 5);  /* End of string. */
674   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
675   check(strstr(one, "abc") == one, 7);  /* Beginning. */
676   check(strstr(one, "abcd") == one, 8); /* Exact match. */
677   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
678   check(strstr(one, "de") == NULL, 10); /* Past end. */
679   check(strstr(one, "") == one, 11);    /* Finding empty. */
680   (void) strcpy(one, "ababa");
681   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
682   (void) strcpy(one, "");
683   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
684   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
685   (void) strcpy(one, "bcbca");
686   check(strstr(one, "bca") == one+2, 15);       /* False start. */
687   (void) strcpy(one, "bbbcabbca");
688   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
689 }
690
691 static void
692 test_strspn (void)
693 {
694   it = "strspn";
695   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
696   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
697   check(strspn("abc", "qx") == 0, 3);   /* None. */
698   check(strspn("", "ab") == 0, 4);      /* Null string. */
699   check(strspn("abc", "") == 0, 5);     /* Null search list. */
700 }
701
702 static void
703 test_strcspn (void)
704 {
705   it = "strcspn";
706   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
707   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
708   check(strcspn("abc", "abc") == 0, 3); /* None. */
709   check(strcspn("", "ab") == 0, 4);     /* Null string. */
710   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
711 }
712
713 static void
714 test_strtok (void)
715 {
716   it = "strtok";
717   (void) strcpy(one, "first, second, third");
718   equal(strtok(one, ", "), "first", 1); /* Basic test. */
719   equal(one, "first", 2);
720   equal(strtok((char *)NULL, ", "), "second", 3);
721   equal(strtok((char *)NULL, ", "), "third", 4);
722   check(strtok((char *)NULL, ", ") == NULL, 5);
723   (void) strcpy(one, ", first, ");
724   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
725   check(strtok((char *)NULL, ", ") == NULL, 7);
726   (void) strcpy(one, "1a, 1b; 2a, 2b");
727   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
728   equal(strtok((char *)NULL, "; "), "1b", 9);
729   equal(strtok((char *)NULL, ", "), "2a", 10);
730   (void) strcpy(two, "x-y");
731   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
732   equal(strtok((char *)NULL, "-"), "y", 12);
733   check(strtok((char *)NULL, "-") == NULL, 13);
734   (void) strcpy(one, "a,b, c,, ,d");
735   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
736   equal(strtok((char *)NULL, ", "), "b", 15);
737   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
738   equal(strtok((char *)NULL, " ,"), "d", 17);
739   check(strtok((char *)NULL, ", ") == NULL, 18);
740   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
741   (void) strcpy(one, ", ");
742   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
743   (void) strcpy(one, "");
744   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
745   (void) strcpy(one, "abc");
746   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
747   check(strtok((char *)NULL, ", ") == NULL, 23);
748   (void) strcpy(one, "abc");
749   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
750   check(strtok((char *)NULL, "") == NULL, 25);
751   (void) strcpy(one, "abcdefgh");
752   (void) strcpy(one, "a,b,c");
753   equal(strtok(one, ","), "a", 26);     /* Basics again... */
754   equal(strtok((char *)NULL, ","), "b", 27);
755   equal(strtok((char *)NULL, ","), "c", 28);
756   check(strtok((char *)NULL, ",") == NULL, 29);
757   equal(one+6, "gh", 30);                       /* Stomped past end? */
758   equal(one, "a", 31);                  /* Stomped old tokens? */
759   equal(one+2, "b", 32);
760   equal(one+4, "c", 33);
761 }
762
763 static void
764 test_strtok_r (void)
765 {
766   it = "strtok_r";
767   (void) strcpy(one, "first, second, third");
768   cp = NULL;    /* Always initialize cp to make sure it doesn't point to some old data.  */
769   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
770   equal(one, "first", 2);
771   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
772   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
773   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
774   (void) strcpy(one, ", first, ");
775   cp = NULL;
776   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
777   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
778   (void) strcpy(one, "1a, 1b; 2a, 2b");
779   cp = NULL;
780   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
781   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
782   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
783   (void) strcpy(two, "x-y");
784   cp = NULL;
785   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
786   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
787   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
788   (void) strcpy(one, "a,b, c,, ,d");
789   cp = NULL;
790   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
791   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
792   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
793   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
794   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
795   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
796   (void) strcpy(one, ", ");
797   cp = NULL;
798   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
799   (void) strcpy(one, "");
800   cp = NULL;
801   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
802   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
803   (void) strcpy(one, "abc");
804   cp = NULL;
805   equal(strtok_r(one, ", ", &cp), "abc", 23);   /* No delimiters. */
806   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
807   (void) strcpy(one, "abc");
808   cp = NULL;
809   equal(strtok_r(one, "", &cp), "abc", 25);     /* Empty delimiter list. */
810   check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
811   (void) strcpy(one, "abcdefgh");
812   (void) strcpy(one, "a,b,c");
813   cp = NULL;
814   equal(strtok_r(one, ",", &cp), "a", 27);      /* Basics again... */
815   equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
816   equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
817   check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
818   equal(one+6, "gh", 31);                       /* Stomped past end? */
819   equal(one, "a", 32);                  /* Stomped old tokens? */
820   equal(one+2, "b", 33);
821   equal(one+4, "c", 34);
822 }
823
824 static void
825 test_strsep (void)
826 {
827   char *ptr;
828   it = "strsep";
829   cp = strcpy(one, "first, second, third");
830   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
831   equal(one, "first", 2);
832   equal(strsep(&cp, ", "), "", 3);
833   equal(strsep(&cp, ", "), "second", 4);
834   equal(strsep(&cp, ", "), "", 5);
835   equal(strsep(&cp, ", "), "third", 6);
836   check(strsep(&cp, ", ") == NULL, 7);
837   cp = strcpy(one, ", first, ");
838   equal(strsep(&cp, ", "), "", 8);
839   equal(strsep(&cp, ", "), "", 9);
840   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
841   equal(strsep(&cp, ", "), "", 11);
842   equal(strsep(&cp, ", "), "", 12);
843   check(strsep(&cp, ", ") == NULL, 13);
844   cp = strcpy(one, "1a, 1b; 2a, 2b");
845   equal(strsep(&cp, ", "), "1a", 14);   /* Changing delim lists. */
846   equal(strsep(&cp, ", "), "", 15);
847   equal(strsep(&cp, "; "), "1b", 16);
848   equal(strsep(&cp, ", "), "", 17);
849   equal(strsep(&cp, ", "), "2a", 18);
850   cp = strcpy(two, "x-y");
851   equal(strsep(&cp, "-"), "x", 19);     /* New string before done. */
852   equal(strsep(&cp, "-"), "y", 20);
853   check(strsep(&cp, "-") == NULL, 21);
854   cp = strcpy(one, "a,b, c,, ,d ");
855   equal(strsep(&cp, ", "), "a", 22);    /* Different separators. */
856   equal(strsep(&cp, ", "), "b", 23);
857   equal(strsep(&cp, " ,"), "", 24);
858   equal(strsep(&cp, " ,"), "c", 25);    /* Permute list too. */
859   equal(strsep(&cp, " ,"), "", 26);
860   equal(strsep(&cp, " ,"), "", 27);
861   equal(strsep(&cp, " ,"), "", 28);
862   equal(strsep(&cp, " ,"), "d", 29);
863   equal(strsep(&cp, " ,"), "", 30);
864   check(strsep(&cp, ", ") == NULL, 31);
865   check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
866   cp = strcpy(one, ", ");
867   equal(strsep(&cp, ", "), "", 33);
868   equal(strsep(&cp, ", "), "", 34);
869   equal(strsep(&cp, ", "), "", 35);
870   check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
871   cp = strcpy(one, "");
872   equal(strsep(&cp, ", "), "", 37);
873   check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
874   cp = strcpy(one, "abc");
875   equal(strsep(&cp, ", "), "abc", 39);  /* No delimiters. */
876   check(strsep(&cp, ", ") == NULL, 40);
877   cp = strcpy(one, "abc");
878   equal(strsep(&cp, ""), "abc", 41);    /* Empty delimiter list. */
879   check(strsep(&cp, "") == NULL, 42);
880   (void) strcpy(one, "abcdefgh");
881   cp = strcpy(one, "a,b,c");
882   equal(strsep(&cp, ","), "a", 43);     /* Basics again... */
883   equal(strsep(&cp, ","), "b", 44);
884   equal(strsep(&cp, ","), "c", 45);
885   check(strsep(&cp, ",") == NULL, 46);
886   equal(one+6, "gh", 47);               /* Stomped past end? */
887   equal(one, "a", 48);                  /* Stomped old tokens? */
888   equal(one+2, "b", 49);
889   equal(one+4, "c", 50);
890
891   {
892     char text[] = "This,is,a,test";
893     char *list = strdupa (text);
894     equal (strsep (&list, ","), "This", 51);
895     equal (strsep (&list, ","), "is", 52);
896     equal (strsep (&list, ","), "a", 53);
897     equal (strsep (&list, ","), "test", 54);
898     check (strsep (&list, ",") == NULL, 55);
899   }
900
901   cp = strcpy(one, "a,b, c,, ,d,");
902   equal(strsep(&cp, ","), "a", 56);     /* Different separators. */
903   equal(strsep(&cp, ","), "b", 57);
904   equal(strsep(&cp, ","), " c", 58);    /* Permute list too. */
905   equal(strsep(&cp, ","), "", 59);
906   equal(strsep(&cp, ","), " ", 60);
907   equal(strsep(&cp, ","), "d", 61);
908   equal(strsep(&cp, ","), "", 62);
909   check(strsep(&cp, ",") == NULL, 63);
910   check(strsep(&cp, ",") == NULL, 64);  /* Persistence. */
911
912   cp = strcpy(one, "a,b, c,, ,d,");
913   equal(strsep(&cp, "xy,"), "a", 65);   /* Different separators. */
914   equal(strsep(&cp, "x,y"), "b", 66);
915   equal(strsep(&cp, ",xy"), " c", 67);  /* Permute list too. */
916   equal(strsep(&cp, "xy,"), "", 68);
917   equal(strsep(&cp, "x,y"), " ", 69);
918   equal(strsep(&cp, ",xy"), "d", 70);
919   equal(strsep(&cp, "xy,"), "", 71);
920   check(strsep(&cp, "x,y") == NULL, 72);
921   check(strsep(&cp, ",xy") == NULL, 73);        /* Persistence. */
922
923   cp = strcpy(one, "ABC");
924   one[4] = ':';
925   equal(strsep(&cp, "C"), "AB", 74);    /* Access beyond NUL.  */
926   ptr = strsep(&cp, ":");
927   equal(ptr, "", 75);
928   check(ptr == one + 3, 76);
929   check(cp == NULL, 77);
930
931   cp = strcpy(one, "ABC");
932   one[4] = ':';
933   equal(strsep(&cp, "CD"), "AB", 78);   /* Access beyond NUL.  */
934   ptr = strsep(&cp, ":.");
935   equal(ptr, "", 79);
936   check(ptr == one + 3, 80);
937
938   cp = strcpy(one, "ABC");              /* No token in string.  */
939   equal(strsep(&cp, ","), "ABC", 81);
940   check(cp == NULL, 82);
941
942   *one = '\0';                          /* Empty string. */
943   cp = one;
944   ptr = strsep(&cp, ",");
945   equal(ptr, "", 83);
946   check(ptr == one, 84);
947   check(cp == NULL, 85);
948
949   *one = '\0';                          /* Empty string and no token. */
950   cp = one;
951   ptr = strsep(&cp, "");
952   equal(ptr, "", 86);
953   check(ptr == one , 87);
954   check(cp == NULL, 88);
955 }
956
957 static void
958 test_memcmp (void)
959 {
960   it = "memcmp";
961   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
962   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
963   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
964   check(memcmp("abce", "abcd", 4) > 0, 4);
965   check(memcmp("alph", "beta", 4) < 0, 5);
966   check(memcmp("a\203", "a\003", 2) > 0, 6);
967   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
968   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
969 }
970
971 static void
972 test_memchr (void)
973 {
974   it = "memchr";
975   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
976   (void) strcpy(one, "abcd");
977   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
978   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
979   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
980   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
981   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
982   (void) strcpy(one, "ababa");
983   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
984   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
985   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
986   (void) strcpy(one, "a\203b");
987   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
988
989   /* now test all possible alignment and length combinations to catch
990      bugs due to unrolled loops (assuming unrolling is limited to no
991      more than 128 byte chunks: */
992   {
993     char buf[128 + sizeof(long)];
994     long align, len, i, pos;
995
996     for (align = 0; align < (long) sizeof(long); ++align) {
997       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
998         for (i = 0; i < len; ++i) {
999           buf[align + i] = 'x';         /* don't depend on memset... */
1000         }
1001         for (pos = 0; pos < len; ++pos) {
1002 #if 0
1003           printf("align %d, len %d, pos %d\n", align, len, pos);
1004 #endif
1005           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1006           check(memchr(buf + align, 'x', pos) == NULL, 11);
1007           buf[align + pos] = '-';
1008         }
1009       }
1010     }
1011   }
1012 }
1013
1014 static void
1015 test_memcpy (void)
1016 {
1017   int i;
1018   it = "memcpy";
1019   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
1020   equal(one, "abc", 2);                 /* Did the copy go right? */
1021
1022   (void) strcpy(one, "abcdefgh");
1023   (void) memcpy(one+1, "xyz", 2);
1024   equal(one, "axydefgh", 3);            /* Basic test. */
1025
1026   (void) strcpy(one, "abc");
1027   (void) memcpy(one, "xyz", 0);
1028   equal(one, "abc", 4);                 /* Zero-length copy. */
1029
1030   (void) strcpy(one, "hi there");
1031   (void) strcpy(two, "foo");
1032   (void) memcpy(two, one, 9);
1033   equal(two, "hi there", 5);            /* Just paranoia. */
1034   equal(one, "hi there", 6);            /* Stomped on source? */
1035
1036   for (i = 0; i < 16; i++)
1037     {
1038       const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1039       strcpy (one, x);
1040       check (memcpy (one + i, "hi there", 9) == one + i,
1041              7 + (i * 6));              /* Unaligned destination. */
1042       check (memcmp (one, x, i) == 0, 8 + (i * 6));  /* Wrote under? */
1043       equal (one + i, "hi there", 9 + (i * 6));
1044       check (one[i + 9] == 'x', 10 + (i * 6));       /* Wrote over? */
1045       check (memcpy (two, one + i, 9) == two,
1046              11 + (i * 6));             /* Unaligned source. */
1047       equal (two, "hi there", 12 + (i * 6));
1048     }
1049 }
1050
1051 static void
1052 test_mempcpy (void)
1053 {
1054   int i;
1055   it = "mempcpy";
1056   check(mempcpy(one, "abc", 4) == one + 4, 1);  /* Returned value. */
1057   equal(one, "abc", 2);                 /* Did the copy go right? */
1058
1059   (void) strcpy(one, "abcdefgh");
1060   (void) mempcpy(one+1, "xyz", 2);
1061   equal(one, "axydefgh", 3);            /* Basic test. */
1062
1063   (void) strcpy(one, "abc");
1064   (void) mempcpy(one, "xyz", 0);
1065   equal(one, "abc", 4);                 /* Zero-length copy. */
1066
1067   (void) strcpy(one, "hi there");
1068   (void) strcpy(two, "foo");
1069   (void) mempcpy(two, one, 9);
1070   equal(two, "hi there", 5);            /* Just paranoia. */
1071   equal(one, "hi there", 6);            /* Stomped on source? */
1072
1073   for (i = 0; i < 16; i++)
1074     {
1075       const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1076       strcpy (one, x);
1077       check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1078              7 + (i * 6));              /* Unaligned destination. */
1079       check (memcmp (one, x, i) == 0, 8 + (i * 6));  /* Wrote under? */
1080       equal (one + i, "hi there", 9 + (i * 6));
1081       check (one[i + 9] == 'x', 10 + (i * 6));       /* Wrote over? */
1082       check (mempcpy (two, one + i, 9) == two + 9,
1083              11 + (i * 6));             /* Unaligned source. */
1084       equal (two, "hi there", 12 + (i * 6));
1085     }
1086 }
1087
1088 static void
1089 test_memmove (void)
1090 {
1091   it = "memmove";
1092   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
1093   equal(one, "abc", 2);                 /* Did the copy go right? */
1094
1095   (void) strcpy(one, "abcdefgh");
1096   (void) memmove(one+1, "xyz", 2);
1097   equal(one, "axydefgh", 3);            /* Basic test. */
1098
1099   (void) strcpy(one, "abc");
1100   (void) memmove(one, "xyz", 0);
1101   equal(one, "abc", 4);                 /* Zero-length copy. */
1102
1103   (void) strcpy(one, "hi there");
1104   (void) strcpy(two, "foo");
1105   (void) memmove(two, one, 9);
1106   equal(two, "hi there", 5);            /* Just paranoia. */
1107   equal(one, "hi there", 6);            /* Stomped on source? */
1108
1109   (void) strcpy(one, "abcdefgh");
1110   (void) memmove(one+1, one, 9);
1111   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
1112
1113   (void) strcpy(one, "abcdefgh");
1114   (void) memmove(one+1, one+2, 7);
1115   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
1116
1117   (void) strcpy(one, "abcdefgh");
1118   (void) memmove(one, one, 9);
1119   equal(one, "abcdefgh", 9);            /* 100% overlap. */
1120 }
1121
1122 static void
1123 test_memccpy (void)
1124 {
1125   /* First test like memcpy, then the search part The SVID, the only
1126      place where memccpy is mentioned, says overlap might fail, so we
1127      don't try it.  Besides, it's hard to see the rationale for a
1128      non-left-to-right memccpy.  */
1129   it = "memccpy";
1130   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
1131   equal(one, "abc", 2);                 /* Did the copy go right? */
1132
1133   (void) strcpy(one, "abcdefgh");
1134   (void) memccpy(one+1, "xyz", 'q', 2);
1135   equal(one, "axydefgh", 3);            /* Basic test. */
1136
1137   (void) strcpy(one, "abc");
1138   (void) memccpy(one, "xyz", 'q', 0);
1139   equal(one, "abc", 4);                 /* Zero-length copy. */
1140
1141   (void) strcpy(one, "hi there");
1142   (void) strcpy(two, "foo");
1143   (void) memccpy(two, one, 'q', 9);
1144   equal(two, "hi there", 5);            /* Just paranoia. */
1145   equal(one, "hi there", 6);            /* Stomped on source? */
1146
1147   (void) strcpy(one, "abcdefgh");
1148   (void) strcpy(two, "horsefeathers");
1149   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1150   equal(one, "abcdefgh", 8);            /* Source intact? */
1151   equal(two, "abcdefeathers", 9);               /* Copy correct? */
1152
1153   (void) strcpy(one, "abcd");
1154   (void) strcpy(two, "bumblebee");
1155   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
1156   equal(two, "aumblebee", 11);
1157   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
1158   equal(two, "abcdlebee", 13);
1159   (void) strcpy(one, "xyz");
1160   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
1161   equal(two, "xbcdlebee", 15);
1162 }
1163
1164 static void
1165 test_memset (void)
1166 {
1167   int i;
1168
1169   it = "memset";
1170   (void) strcpy(one, "abcdefgh");
1171   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
1172   equal(one, "axxxefgh", 2);            /* Basic test. */
1173
1174   (void) memset(one+2, 'y', 0);
1175   equal(one, "axxxefgh", 3);            /* Zero-length set. */
1176
1177   (void) memset(one+5, 0, 1);
1178   equal(one, "axxxe", 4);                       /* Zero fill. */
1179   equal(one+6, "gh", 5);                        /* And the leftover. */
1180
1181   (void) memset(one+2, 010045, 1);
1182   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
1183
1184   /* Non-8bit fill character.  */
1185   memset (one, 0x101, sizeof (one));
1186   for (i = 0; i < (int) sizeof (one); ++i)
1187     check (one[i] == '\01', 7);
1188
1189   /* Test for more complex versions of memset, for all alignments and
1190      lengths up to 256. This test takes a little while, perhaps it should
1191      be made weaker?  */
1192   {
1193     char data[512];
1194     int j;
1195     int k;
1196     int c;
1197
1198     for (i = 0; i < 512; i++)
1199       data[i] = 'x';
1200     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
1201                                         memset(,'y',) */
1202       for (j = 0; j < 256; j++)
1203         for (i = 0; i < 256; i++)
1204           {
1205             memset (data + i, c, j);
1206             for (k = 0; k < i; k++)
1207               if (data[k] != 'x')
1208                 goto fail;
1209             for (k = i; k < i+j; k++)
1210               {
1211                 if (data[k] != c)
1212                   goto fail;
1213                 data[k] = 'x';
1214               }
1215             for (k = i+j; k < 512; k++)
1216               if (data[k] != 'x')
1217                 goto fail;
1218             continue;
1219
1220           fail:
1221             check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1222           }
1223   }
1224 }
1225
1226 static void
1227 test_bcopy (void)
1228 {
1229   /* Much like memcpy.  Berklix manual is silent about overlap, so
1230      don't test it.  */
1231   it = "bcopy";
1232   (void) bcopy("abc", one, 4);
1233   equal(one, "abc", 1);                 /* Simple copy. */
1234
1235   (void) strcpy(one, "abcdefgh");
1236   (void) bcopy("xyz", one+1, 2);
1237   equal(one, "axydefgh", 2);            /* Basic test. */
1238
1239   (void) strcpy(one, "abc");
1240   (void) bcopy("xyz", one, 0);
1241   equal(one, "abc", 3);                 /* Zero-length copy. */
1242
1243   (void) strcpy(one, "hi there");
1244   (void) strcpy(two, "foo");
1245   (void) bcopy(one, two, 9);
1246   equal(two, "hi there", 4);            /* Just paranoia. */
1247   equal(one, "hi there", 5);            /* Stomped on source? */
1248 }
1249
1250 static void
1251 test_bzero (void)
1252 {
1253   it = "bzero";
1254   (void) strcpy(one, "abcdef");
1255   bzero(one+2, 2);
1256   equal(one, "ab", 1);                  /* Basic test. */
1257   equal(one+3, "", 2);
1258   equal(one+4, "ef", 3);
1259
1260   (void) strcpy(one, "abcdef");
1261   bzero(one+2, 0);
1262   equal(one, "abcdef", 4);              /* Zero-length copy. */
1263 }
1264
1265 static void
1266 test_strndup (void)
1267 {
1268   char *p, *q;
1269   it = "strndup";
1270   p = strndup("abcdef", 12);
1271   check(p != NULL, 1);
1272   if (p != NULL)
1273     {
1274       equal(p, "abcdef", 2);
1275       q = strndup(p + 1, 2);
1276       check(q != NULL, 3);
1277       if (q != NULL)
1278         equal(q, "bc", 4);
1279       free (q);
1280     }
1281   free (p);
1282   p = strndup("abc def", 3);
1283   check(p != NULL, 5);
1284   if (p != NULL)
1285     equal(p, "abc", 6);
1286   free (p);
1287 }
1288
1289 static void
1290 test_bcmp (void)
1291 {
1292   it = "bcmp";
1293   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
1294   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1295   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
1296   check(bcmp("abce", "abcd", 4) != 0, 4);
1297   check(bcmp("alph", "beta", 4) != 0, 5);
1298   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
1299   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1300 }
1301
1302 static void
1303 test_strerror (void)
1304 {
1305   it = "strerror";
1306   check(strerror(EDOM) != 0, 1);
1307   check(strerror(ERANGE) != 0, 2);
1308   check(strerror(ENOENT) != 0, 3);
1309 }
1310
1311 static void
1312 test_strcasecmp (void)
1313 {
1314   it = "strcasecmp";
1315   /* Note that the locale is "C".  */
1316   check(strcasecmp("a", "a") == 0, 1);
1317   check(strcasecmp("a", "A") == 0, 2);
1318   check(strcasecmp("A", "a") == 0, 3);
1319   check(strcasecmp("a", "b") < 0, 4);
1320   check(strcasecmp("c", "b") > 0, 5);
1321   check(strcasecmp("abc", "AbC") == 0, 6);
1322   check(strcasecmp("0123456789", "0123456789") == 0, 7);
1323   check(strcasecmp("", "0123456789") < 0, 8);
1324   check(strcasecmp("AbC", "") > 0, 9);
1325   check(strcasecmp("AbC", "A") > 0, 10);
1326   check(strcasecmp("AbC", "Ab") > 0, 11);
1327   check(strcasecmp("AbC", "ab") > 0, 12);
1328 }
1329
1330 static void
1331 test_strncasecmp (void)
1332 {
1333   it = "strncasecmp";
1334   /* Note that the locale is "C".  */
1335   check(strncasecmp("a", "a", 5) == 0, 1);
1336   check(strncasecmp("a", "A", 5) == 0, 2);
1337   check(strncasecmp("A", "a", 5) == 0, 3);
1338   check(strncasecmp("a", "b", 5) < 0, 4);
1339   check(strncasecmp("c", "b", 5) > 0, 5);
1340   check(strncasecmp("abc", "AbC", 5) == 0, 6);
1341   check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1342   check(strncasecmp("", "0123456789", 10) < 0, 8);
1343   check(strncasecmp("AbC", "", 5) > 0, 9);
1344   check(strncasecmp("AbC", "A", 5) > 0, 10);
1345   check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1346   check(strncasecmp("AbC", "ab", 5) > 0, 12);
1347   check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1348   check(strncasecmp("AbC", "abc", 1) == 0, 14);
1349   check(strncasecmp("AbC", "abc", 2) == 0, 15);
1350   check(strncasecmp("AbC", "abc", 3) == 0, 16);
1351   check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1352   check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1353   check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1354   check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1355 }
1356
1357 int
1358 main (void)
1359 {
1360   int status;
1361
1362   /* Test strcmp first because we use it to test other things.  */
1363   test_strcmp ();
1364
1365   /* Test strcpy next because we need it to set up other tests.  */
1366   test_strcpy ();
1367
1368   /* A closely related function is stpcpy.  */
1369   test_stpcpy ();
1370
1371   /* stpncpy.  */
1372   test_stpncpy ();
1373
1374   /* strcat.  */
1375   test_strcat ();
1376
1377   /* strncat.  */
1378   test_strncat ();
1379
1380   /* strncmp.  */
1381   test_strncmp ();
1382
1383   /* strncpy.  */
1384   test_strncpy ();
1385
1386   /* strlen.  */
1387   test_strlen ();
1388
1389   /* strchr.  */
1390   test_strchr ();
1391
1392   /* strchrnul.  */
1393   test_strchrnul ();
1394
1395   /* rawmemchr.  */
1396   test_rawmemchr ();
1397
1398   /* index - just like strchr.  */
1399   test_index ();
1400
1401   /* strrchr.  */
1402   test_strrchr ();
1403
1404   /* memrchr.  */
1405   test_memrchr ();
1406
1407   /* rindex - just like strrchr.  */
1408   test_rindex ();
1409
1410   /* strpbrk - somewhat like strchr.  */
1411   test_strpbrk ();
1412
1413   /* strstr - somewhat like strchr.  */
1414   test_strstr ();
1415
1416   /* strspn.  */
1417   test_strspn ();
1418
1419   /* strcspn.  */
1420   test_strcspn ();
1421
1422   /* strtok - the hard one.  */
1423   test_strtok ();
1424
1425   /* strtok_r.  */
1426   test_strtok_r ();
1427
1428   /* strsep.  */
1429   test_strsep ();
1430
1431   /* memcmp.  */
1432   test_memcmp ();
1433
1434   /* memchr.  */
1435   test_memchr ();
1436
1437   /* memcpy - need not work for overlap.  */
1438   test_memcpy ();
1439
1440   /* memmove - must work on overlap.  */
1441   test_memmove ();
1442
1443   /* mempcpy */
1444   test_mempcpy ();
1445
1446   /* memccpy.  */
1447   test_memccpy ();
1448
1449   /* memset.  */
1450   test_memset ();
1451
1452   /* bcopy.  */
1453   test_bcopy ();
1454
1455   /* bzero.  */
1456   test_bzero ();
1457
1458   /* bcmp - somewhat like memcmp.  */
1459   test_bcmp ();
1460
1461   /* strndup.  */
1462   test_strndup ();
1463
1464   /* strerror - VERY system-dependent.  */
1465   test_strerror ();
1466
1467   /* strcasecmp.  Without locale dependencies.  */
1468   test_strcasecmp ();
1469
1470   /* strncasecmp.  Without locale dependencies.  */
1471   test_strncasecmp ();
1472
1473   if (errors == 0)
1474     {
1475       status = EXIT_SUCCESS;
1476       puts("No errors.");
1477     }
1478   else
1479     {
1480       status = EXIT_FAILURE;
1481       printf("%Zd errors.\n", errors);
1482     }
1483
1484   return status;
1485 }