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