Add copyright and make little cleanups.
[kopensolaris-gnu/glibc.git] / string / tester.c
1 /* Tester for string functions.
2    Copyright (C) 1995, 1996, 1997 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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 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 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 void equal (const char *a, const char *b, int number)
60 {
61   check(a != NULL && b != NULL && STREQ (a, b), number);
62 }
63
64 char one[50];
65 char two[50];
66
67 int
68 main (void)
69 {
70   char *cp;
71
72   /* Test strcmp first because we use it to test other things.  */
73   it = "strcmp";
74   check (strcmp ("", "") == 0, 1);              /* Trivial case. */
75   check (strcmp ("a", "a") == 0, 2);            /* Identity. */
76   check (strcmp ("abc", "abc") == 0, 3);        /* Multicharacter. */
77   check (strcmp ("abc", "abcd") < 0, 4);        /* Length mismatches. */
78   check (strcmp ("abcd", "abc") > 0, 5);
79   check (strcmp ("abcd", "abce") < 0, 6);       /* Honest miscompares. */
80   check (strcmp ("abce", "abcd") > 0, 7);
81   check (strcmp ("a\203", "a") > 0, 8);         /* Tricky if char signed. */
82   check (strcmp ("a\203", "a\003") > 0, 9);
83
84   {
85     char buf1[0x40], buf2[0x40];
86     int i, j;
87     for (i=0; i < 0x10; i++)
88       for (j = 0; j < 0x10; j++)
89         {
90           int k;
91           for (k = 0; k < 0x3f; k++)
92             {
93               buf1[j] = '0' ^ (k & 4);
94               buf2[j] = '4' ^ (k & 4);
95             }
96           buf1[i] = buf1[0x3f] = 0;
97           buf2[j] = buf2[0x3f] = 0;
98           for (k = 0; k < 0xf; k++)
99             {
100               int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
101               check (strcmp (buf1+i,buf2+j) == 0, cnum);
102               buf1[i+k] = 'A' + i + k;
103               buf1[i+k+1] = 0;
104               check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
105               check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
106               buf2[j+k] = 'B' + i + k;
107               buf2[j+k+1] = 0;
108               check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
109               check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
110               buf2[j+k] = 'A' + i + k;
111               buf1[i] = 'A' + i + 0x80;
112               check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
113               check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
114               buf1[i] = 'A' + i;
115             }
116         }
117   }
118
119   /* Test strcpy next because we need it to set up other tests.  */
120   it = "strcpy";
121   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
122   equal (one, "abcd", 2);               /* Basic test. */
123
124   (void) strcpy (one, "x");
125   equal (one, "x", 3);                  /* Writeover. */
126   equal (one+2, "cd", 4);               /* Wrote too much? */
127
128   (void) strcpy (two, "hi there");
129   (void) strcpy (one, two);
130   equal (one, "hi there", 5);           /* Basic test encore. */
131   equal (two, "hi there", 6);           /* Stomped on source? */
132
133   (void) strcpy (one, "");
134   equal (one, "", 7);                   /* Boundary condition. */
135
136   /* A closely related function is stpcpy.  */
137   it = "stpcpy";
138   check ((stpcpy (one, "abcde") - one) == 5, 1);
139   equal (one, "abcde", 2);
140
141   check ((stpcpy (one, "x") - one) == 1, 3);
142   equal (one, "x", 4);                  /* Writeover. */
143   equal (one+2, "cde", 5);              /* Wrote too much? */
144
145   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 6);
146   equal (one, "abc", 7);
147   equal (one + 4, "e", 8);
148
149   /* stpncpy.  */
150   it = "stpncpy";
151
152   memset (one, 'x', sizeof (one));
153   check (stpncpy (one, "abc", 2) == one + 2, 1);
154   check (stpncpy (one, "abc", 3) == one + 3, 2);
155   check (stpncpy (one, "abc", 4) == one + 3, 3);
156   check (one[3] == '\0' && one[4] == 'x', 4);
157   check (stpncpy (one, "abcd", 5) == one + 4, 5);
158   check (one[4] == '\0' && one[5] == 'x', 6);
159   check (stpncpy (one, "abcd", 6) == one + 4, 7);
160   check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
161
162   /* strcat.  */
163   it = "strcat";
164   (void) strcpy (one, "ijk");
165   check (strcat (one, "lmn") == one, 1); /* Returned value. */
166   equal (one, "ijklmn", 2);             /* Basic test. */
167
168   (void) strcpy (one, "x");
169   (void) strcat (one, "yz");
170   equal (one, "xyz", 3);                        /* Writeover. */
171   equal (one+4, "mn", 4);                       /* Wrote too much? */
172
173   (void) strcpy (one, "gh");
174   (void) strcpy (two, "ef");
175   (void) strcat (one, two);
176   equal (one, "ghef", 5);                       /* Basic test encore. */
177   equal (two, "ef", 6);                 /* Stomped on source? */
178
179   (void) strcpy (one, "");
180   (void) strcat (one, "");
181   equal (one, "", 7);                   /* Boundary conditions. */
182   (void) strcpy (one, "ab");
183   (void) strcat (one, "");
184   equal (one, "ab", 8);
185   (void) strcpy (one, "");
186   (void) strcat (one, "cd");
187   equal (one, "cd", 9);
188
189   /* strncat - first test it as strcat, with big counts,
190      then test the count mechanism.  */
191   it = "strncat";
192   (void) strcpy (one, "ijk");
193   check (strncat (one, "lmn", 99) == one, 1);   /* Returned value. */
194   equal (one, "ijklmn", 2);             /* Basic test. */
195
196   (void) strcpy (one, "x");
197   (void) strncat (one, "yz", 99);
198   equal (one, "xyz", 3);                /* Writeover. */
199   equal (one+4, "mn", 4);               /* Wrote too much? */
200
201   (void) strcpy (one, "gh");
202   (void) strcpy (two, "ef");
203   (void) strncat (one, two, 99);
204   equal (one, "ghef", 5);                       /* Basic test encore. */
205   equal (two, "ef", 6);                 /* Stomped on source? */
206
207   (void) strcpy (one, "");
208   (void) strncat (one, "", 99);
209   equal (one, "", 7);                   /* Boundary conditions. */
210   (void) strcpy (one, "ab");
211   (void) strncat (one, "", 99);
212   equal (one, "ab", 8);
213   (void) strcpy (one, "");
214   (void) strncat (one, "cd", 99);
215   equal (one, "cd", 9);
216
217   (void) strcpy (one, "ab");
218   (void) strncat (one, "cdef", 2);
219   equal (one, "abcd", 10);                      /* Count-limited. */
220
221   (void) strncat (one, "gh", 0);
222   equal (one, "abcd", 11);                      /* Zero count. */
223
224   (void) strncat (one, "gh", 2);
225   equal (one, "abcdgh", 12);            /* Count and length equal. */
226
227   /* strncmp - first test as strcmp with big counts,
228      then test count code.  */
229   it = "strncmp";
230   check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
231   check (strncmp ("a", "a", 99) == 0, 2);       /* Identity. */
232   check (strncmp ("abc", "abc", 99) == 0, 3);   /* Multicharacter. */
233   check (strncmp ("abc", "abcd", 99) < 0, 4);   /* Length unequal. */
234   check (strncmp ("abcd", "abc", 99) > 0, 5);
235   check (strncmp ("abcd", "abce", 99) < 0, 6);  /* Honestly unequal. */
236   check (strncmp ("abce", "abcd", 99) > 0, 7);
237   check (strncmp ("a\203", "a", 2) > 0, 8);     /* Tricky if '\203' < 0 */
238   check (strncmp ("a\203", "a\003", 2) > 0, 9);
239   check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
240   check (strncmp ("abce", "abc", 3) == 0, 11);  /* Count == length. */
241   check (strncmp ("abcd", "abce", 4) < 0, 12);  /* Nudging limit. */
242   check (strncmp ("abc", "def", 0) == 0, 13);   /* Zero count. */
243
244   /* strncpy - testing is a bit different because of odd semantics.  */
245   it = "strncpy";
246   check (strncpy (one, "abc", 4) == one, 1);    /* Returned value. */
247   equal (one, "abc", 2);                        /* Did the copy go right? */
248
249   (void) strcpy (one, "abcdefgh");
250   (void) strncpy (one, "xyz", 2);
251   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
252
253   (void) strcpy (one, "abcdefgh");
254   (void) strncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
255   equal (one, "xyzdefgh", 4);
256
257   (void) strcpy (one, "abcdefgh");
258   (void) strncpy (one, "xyz", 4);               /* Copy just includes NUL. */
259   equal (one, "xyz", 5);
260   equal (one+4, "efgh", 6);                     /* Wrote too much? */
261
262   (void) strcpy (one, "abcdefgh");
263   (void) strncpy (one, "xyz", 5);               /* Copy includes padding. */
264   equal (one, "xyz", 7);
265   equal (one+4, "", 8);
266   equal (one+5, "fgh", 9);
267
268   (void) strcpy (one, "abc");
269   (void) strncpy (one, "xyz", 0);               /* Zero-length copy. */
270   equal (one, "abc", 10);
271
272   (void) strncpy (one, "", 2);          /* Zero-length source. */
273   equal (one, "", 11);
274   equal (one+1, "", 12);
275   equal (one+2, "c", 13);
276
277   (void) strcpy (one, "hi there");
278   (void) strncpy (two, one, 9);
279   equal (two, "hi there", 14);          /* Just paranoia. */
280   equal (one, "hi there", 15);          /* Stomped on source? */
281
282   /* strlen.  */
283   it = "strlen";
284   check (strlen ("") == 0, 1);          /* Empty. */
285   check (strlen ("a") == 1, 2);         /* Single char. */
286   check (strlen ("abcd") == 4, 3);      /* Multiple chars. */
287   {
288     char buf[4096];
289     int i;
290     char *p;
291     for (i=0; i < 0x100; i++)
292       {
293         p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
294         strcpy (p, "OK");
295         strcpy (p+3, "BAD/WRONG");
296         check (strlen (p) == 2, 4+i);
297       }
298    }
299
300   /* strchr.  */
301   it = "strchr";
302   check (strchr ("abcd", 'z') == NULL, 1);      /* Not found. */
303   (void) strcpy (one, "abcd");
304   check (strchr (one, 'c') == one+2, 2);        /* Basic test. */
305   check (strchr (one, 'd') == one+3, 3);        /* End of string. */
306   check (strchr (one, 'a') == one, 4);          /* Beginning. */
307   check (strchr (one, '\0') == one+4, 5);       /* Finding NUL. */
308   (void) strcpy (one, "ababa");
309   check (strchr (one, 'b') == one+1, 6);        /* Finding first. */
310   (void) strcpy (one, "");
311   check (strchr (one, 'b') == NULL, 7);         /* Empty string. */
312   check (strchr (one, '\0') == one, 8);         /* NUL in empty string. */
313   {
314     char buf[4096];
315     int i;
316     char *p;
317     for (i=0; i < 0x100; i++)
318       {
319         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
320         strcpy (p, "OK");
321         strcpy (p+3, "BAD/WRONG");
322         check (strchr (p, '/') == NULL, 9+i);
323       }
324    }
325
326 #if 0
327   /* index - just like strchr.  */
328   it = "index";
329   check (index ("abcd", 'z') == NULL, 1);       /* Not found. */
330   (void) strcpy (one, "abcd");
331   check (index (one, 'c') == one+2, 2); /* Basic test. */
332   check (index (one, 'd') == one+3, 3); /* End of string. */
333   check (index (one, 'a') == one, 4);   /* Beginning. */
334   check (index (one, '\0') == one+4, 5);        /* Finding NUL. */
335   (void) strcpy (one, "ababa");
336   check (index (one, 'b') == one+1, 6); /* Finding first. */
337   (void) strcpy (one, "");
338   check (index (one, 'b') == NULL, 7);  /* Empty string. */
339   check (index (one, '\0') == one, 8);  /* NUL in empty string. */
340 #endif
341
342   /* strrchr.  */
343   it = "strrchr";
344   check (strrchr ("abcd", 'z') == NULL, 1);     /* Not found. */
345   (void) strcpy (one, "abcd");
346   check (strrchr (one, 'c') == one+2, 2);       /* Basic test. */
347   check (strrchr (one, 'd') == one+3, 3);       /* End of string. */
348   check (strrchr (one, 'a') == one, 4);         /* Beginning. */
349   check (strrchr (one, '\0') == one+4, 5);      /* Finding NUL. */
350   (void) strcpy (one, "ababa");
351   check (strrchr (one, 'b') == one+3, 6);       /* Finding last. */
352   (void) strcpy (one, "");
353   check (strrchr (one, 'b') == NULL, 7);        /* Empty string. */
354   check (strrchr (one, '\0') == one, 8);        /* NUL in empty string. */
355   {
356     char buf[4096];
357     int i;
358     char *p;
359     for (i=0; i < 0x100; i++)
360       {
361         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
362         strcpy (p, "OK");
363         strcpy (p+3, "BAD/WRONG");
364         check (strrchr (p, '/') == NULL, 9+i);
365       }
366    }
367
368 #if 0
369   /* rindex - just like strrchr.  */
370   it = "rindex";
371   check (rindex ("abcd", 'z') == NULL, 1);      /* Not found. */
372   (void) strcpy (one, "abcd");
373   check (rindex (one, 'c') == one+2, 2);        /* Basic test. */
374   check (rindex (one, 'd') == one+3, 3);        /* End of string. */
375   check (rindex (one, 'a') == one, 4);  /* Beginning. */
376   check (rindex (one, '\0') == one+4, 5);       /* Finding NUL. */
377   (void) strcpy (one, "ababa");
378   check (rindex (one, 'b') == one+3, 6);        /* Finding last. */
379   (void) strcpy (one, "");
380   check (rindex (one, 'b') == NULL, 7); /* Empty string. */
381   check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
382 #endif
383
384   /* strpbrk - somewhat like strchr.  */
385   it = "strpbrk";
386   check(strpbrk("abcd", "z") == NULL, 1);       /* Not found. */
387   (void) strcpy(one, "abcd");
388   check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
389   check(strpbrk(one, "d") == one+3, 3); /* End of string. */
390   check(strpbrk(one, "a") == one, 4);   /* Beginning. */
391   check(strpbrk(one, "") == NULL, 5);   /* Empty search list. */
392   check(strpbrk(one, "cb") == one+1, 6);        /* Multiple search. */
393   (void) strcpy(one, "abcabdea");
394   check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
395   check(strpbrk(one, "cb") == one+1, 8);        /* With multiple search. */
396   check(strpbrk(one, "db") == one+1, 9);        /* Another variant. */
397   (void) strcpy(one, "");
398   check(strpbrk(one, "bc") == NULL, 10);        /* Empty string. */
399   check(strpbrk(one, "") == NULL, 11);  /* Both strings empty. */
400
401   /* strstr - somewhat like strchr.  */
402   it = "strstr";
403   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
404   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
405   (void) strcpy(one, "abcd");
406   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
407   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
408   check(strstr(one, "d") == one+3, 5);  /* End of string. */
409   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
410   check(strstr(one, "abc") == one, 7);  /* Beginning. */
411   check(strstr(one, "abcd") == one, 8); /* Exact match. */
412   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
413   check(strstr(one, "de") == NULL, 10); /* Past end. */
414   check(strstr(one, "") == one, 11);    /* Finding empty. */
415   (void) strcpy(one, "ababa");
416   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
417   (void) strcpy(one, "");
418   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
419   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
420   (void) strcpy(one, "bcbca");
421   check(strstr(one, "bca") == one+2, 15);       /* False start. */
422   (void) strcpy(one, "bbbcabbca");
423   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
424
425   /* strspn.  */
426   it = "strspn";
427   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
428   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
429   check(strspn("abc", "qx") == 0, 3);   /* None. */
430   check(strspn("", "ab") == 0, 4);      /* Null string. */
431   check(strspn("abc", "") == 0, 5);     /* Null search list. */
432
433   /* strcspn.  */
434   it = "strcspn";
435   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
436   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
437   check(strcspn("abc", "abc") == 0, 3); /* None. */
438   check(strcspn("", "ab") == 0, 4);     /* Null string. */
439   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
440
441   /* strtok - the hard one.  */
442   it = "strtok";
443   (void) strcpy(one, "first, second, third");
444   equal(strtok(one, ", "), "first", 1); /* Basic test. */
445   equal(one, "first", 2);
446   equal(strtok((char *)NULL, ", "), "second", 3);
447   equal(strtok((char *)NULL, ", "), "third", 4);
448   check(strtok((char *)NULL, ", ") == NULL, 5);
449   (void) strcpy(one, ", first, ");
450   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
451   check(strtok((char *)NULL, ", ") == NULL, 7);
452   (void) strcpy(one, "1a, 1b; 2a, 2b");
453   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
454   equal(strtok((char *)NULL, "; "), "1b", 9);
455   equal(strtok((char *)NULL, ", "), "2a", 10);
456   (void) strcpy(two, "x-y");
457   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
458   equal(strtok((char *)NULL, "-"), "y", 12);
459   check(strtok((char *)NULL, "-") == NULL, 13);
460   (void) strcpy(one, "a,b, c,, ,d");
461   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
462   equal(strtok((char *)NULL, ", "), "b", 15);
463   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
464   equal(strtok((char *)NULL, " ,"), "d", 17);
465   check(strtok((char *)NULL, ", ") == NULL, 18);
466   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
467   (void) strcpy(one, ", ");
468   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
469   (void) strcpy(one, "");
470   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
471   (void) strcpy(one, "abc");
472   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
473   check(strtok((char *)NULL, ", ") == NULL, 23);
474   (void) strcpy(one, "abc");
475   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
476   check(strtok((char *)NULL, "") == NULL, 25);
477   (void) strcpy(one, "abcdefgh");
478   (void) strcpy(one, "a,b,c");
479   equal(strtok(one, ","), "a", 26);     /* Basics again... */
480   equal(strtok((char *)NULL, ","), "b", 27);
481   equal(strtok((char *)NULL, ","), "c", 28);
482   check(strtok((char *)NULL, ",") == NULL, 29);
483   equal(one+6, "gh", 30);                       /* Stomped past end? */
484   equal(one, "a", 31);                  /* Stomped old tokens? */
485   equal(one+2, "b", 32);
486   equal(one+4, "c", 33);
487
488   /* strtok_r.  */
489   it = "strtok_r";
490   (void) strcpy(one, "first, second, third");
491   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
492   equal(one, "first", 2);
493   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
494   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
495   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
496   (void) strcpy(one, ", first, ");
497   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
498   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
499   (void) strcpy(one, "1a, 1b; 2a, 2b");
500   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
501   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
502   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
503   (void) strcpy(two, "x-y");
504   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
505   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
506   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
507   (void) strcpy(one, "a,b, c,, ,d");
508   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
509   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
510   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
511   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
512   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
513   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
514   (void) strcpy(one, ", ");
515   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
516   (void) strcpy(one, "");
517   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
518   (void) strcpy(one, "abc");
519   equal(strtok_r(one, ", ", &cp), "abc", 22);   /* No delimiters. */
520   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
521   (void) strcpy(one, "abc");
522   equal(strtok_r(one, "", &cp), "abc", 24);     /* Empty delimiter list. */
523   check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
524   (void) strcpy(one, "abcdefgh");
525   (void) strcpy(one, "a,b,c");
526   equal(strtok_r(one, ",", &cp), "a", 26);      /* Basics again... */
527   equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
528   equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
529   check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
530   equal(one+6, "gh", 30);                       /* Stomped past end? */
531   equal(one, "a", 31);                  /* Stomped old tokens? */
532   equal(one+2, "b", 32);
533   equal(one+4, "c", 33);
534
535   /* strsep.  */
536   it = "strsep";
537   cp = strcpy(one, "first, second, third");
538   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
539   equal(one, "first", 2);
540   equal(strsep(&cp, ", "), "", 3);
541   equal(strsep(&cp, ", "), "second", 4);
542   equal(strsep(&cp, ", "), "", 5);
543   equal(strsep(&cp, ", "), "third", 6);
544   check(strsep(&cp, ", ") == NULL, 7);
545   cp = strcpy(one, ", first, ");
546   equal(strsep(&cp, ", "), "", 8);
547   equal(strsep(&cp, ", "), "", 9);
548   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
549   equal(strsep(&cp, ", "), "", 11);
550   check(strsep(&cp, ", ") == NULL, 12);
551   cp = strcpy(one, "1a, 1b; 2a, 2b");
552   equal(strsep(&cp, ", "), "1a", 13);   /* Changing delim lists. */
553   equal(strsep(&cp, ", "), "", 14);
554   equal(strsep(&cp, "; "), "1b", 15);
555   equal(strsep(&cp, ", "), "", 16);
556   equal(strsep(&cp, ", "), "2a", 17);
557   cp = strcpy(two, "x-y");
558   equal(strsep(&cp, "-"), "x", 18);     /* New string before done. */
559   equal(strsep(&cp, "-"), "y", 19);
560   check(strsep(&cp, "-") == NULL, 20);
561   cp = strcpy(one, "a,b, c,, ,d");
562   equal(strsep(&cp, ", "), "a", 21);    /* Different separators. */
563   equal(strsep(&cp, ", "), "b", 22);
564   equal(strsep(&cp, " ,"), "", 23);
565   equal(strsep(&cp, " ,"), "c", 24);    /* Permute list too. */
566   equal(strsep(&cp, " ,"), "", 25);
567   equal(strsep(&cp, " ,"), "", 26);
568   equal(strsep(&cp, " ,"), "", 27);
569   equal(strsep(&cp, " ,"), "d", 28);
570   check(strsep(&cp, ", ") == NULL, 29);
571   check(strsep(&cp, ", ") == NULL, 30); /* Persistence. */
572   cp = strcpy(one, ", ");
573   equal(strsep(&cp, ", "), "", 31);
574   equal(strsep(&cp, ", "), "", 32);
575   check(strsep(&cp, ", ") == NULL, 33); /* No tokens. */
576   cp = strcpy(one, "");
577   check(strsep(&cp, ", ") == NULL, 34); /* Empty string. */
578   cp = strcpy(one, "abc");
579   equal(strsep(&cp, ", "), "abc", 35);  /* No delimiters. */
580   check(strsep(&cp, ", ") == NULL, 36);
581   cp = strcpy(one, "abc");
582   equal(strsep(&cp, ""), "abc", 37);    /* Empty delimiter list. */
583   check(strsep(&cp, "") == NULL, 38);
584   (void) strcpy(one, "abcdefgh");
585   cp = strcpy(one, "a,b,c");
586   equal(strsep(&cp, ","), "a", 39);     /* Basics again... */
587   equal(strsep(&cp, ","), "b", 40);
588   equal(strsep(&cp, ","), "c", 41);
589   check(strsep(&cp, ",") == NULL, 42);
590   equal(one+6, "gh", 43);               /* Stomped past end? */
591   equal(one, "a", 44);                  /* Stomped old tokens? */
592   equal(one+2, "b", 45);
593   equal(one+4, "c", 46);
594
595   /* memcmp.  */
596   it = "memcmp";
597   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
598   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
599   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
600   check(memcmp("abce", "abcd", 4) > 0, 4);
601   check(memcmp("alph", "beta", 4) < 0, 5);
602   check(memcmp("a\203", "a\003", 2) > 0, 6);
603   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
604   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
605
606   /* memchr.  */
607   it = "memchr";
608   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
609   (void) strcpy(one, "abcd");
610   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
611   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
612   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
613   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
614   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
615   (void) strcpy(one, "ababa");
616   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
617   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
618   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
619   (void) strcpy(one, "a\203b");
620   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
621
622   /* now test all possible alignment and length combinations to catch
623      bugs due to unrolled loops (assuming unrolling is limited to no
624      more than 128 byte chunks: */
625   {
626     char buf[128 + sizeof(long)];
627     long align, len, i, pos;
628
629     for (align = 0; align < (long) sizeof(long); ++align) {
630       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
631         for (i = 0; i < len; ++i) {
632           buf[align + i] = 'x';         /* don't depend on memset... */
633         }
634         for (pos = 0; pos < len; ++pos) {
635 #if 0
636           printf("align %d, len %d, pos %d\n", align, len, pos);
637 #endif
638           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
639           check(memchr(buf + align, 'x', pos) == NULL, 11);
640           buf[align + pos] = '-';
641         }
642       }
643     }
644   }
645
646   /* memcpy - need not work for overlap.  */
647   it = "memcpy";
648   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
649   equal(one, "abc", 2);                 /* Did the copy go right? */
650
651   (void) strcpy(one, "abcdefgh");
652   (void) memcpy(one+1, "xyz", 2);
653   equal(one, "axydefgh", 3);            /* Basic test. */
654
655   (void) strcpy(one, "abc");
656   (void) memcpy(one, "xyz", 0);
657   equal(one, "abc", 4);                 /* Zero-length copy. */
658
659   (void) strcpy(one, "hi there");
660   (void) strcpy(two, "foo");
661   (void) memcpy(two, one, 9);
662   equal(two, "hi there", 5);            /* Just paranoia. */
663   equal(one, "hi there", 6);            /* Stomped on source? */
664
665   /* memmove - must work on overlap.  */
666   it = "memmove";
667   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
668   equal(one, "abc", 2);                 /* Did the copy go right? */
669
670   (void) strcpy(one, "abcdefgh");
671   (void) memmove(one+1, "xyz", 2);
672   equal(one, "axydefgh", 3);            /* Basic test. */
673
674   (void) strcpy(one, "abc");
675   (void) memmove(one, "xyz", 0);
676   equal(one, "abc", 4);                 /* Zero-length copy. */
677
678   (void) strcpy(one, "hi there");
679   (void) strcpy(two, "foo");
680   (void) memmove(two, one, 9);
681   equal(two, "hi there", 5);            /* Just paranoia. */
682   equal(one, "hi there", 6);            /* Stomped on source? */
683
684   (void) strcpy(one, "abcdefgh");
685   (void) memmove(one+1, one, 9);
686   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
687
688   (void) strcpy(one, "abcdefgh");
689   (void) memmove(one+1, one+2, 7);
690   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
691
692   (void) strcpy(one, "abcdefgh");
693   (void) memmove(one, one, 9);
694   equal(one, "abcdefgh", 9);            /* 100% overlap. */
695
696   /* memccpy - first test like memcpy, then the search part
697      The SVID, the only place where memccpy is mentioned, says
698      overlap might fail, so we don't try it.  Besides, it's hard
699      to see the rationale for a non-left-to-right memccpy.  */
700   it = "memccpy";
701   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
702   equal(one, "abc", 2);                 /* Did the copy go right? */
703
704   (void) strcpy(one, "abcdefgh");
705   (void) memccpy(one+1, "xyz", 'q', 2);
706   equal(one, "axydefgh", 3);            /* Basic test. */
707
708   (void) strcpy(one, "abc");
709   (void) memccpy(one, "xyz", 'q', 0);
710   equal(one, "abc", 4);                 /* Zero-length copy. */
711
712   (void) strcpy(one, "hi there");
713   (void) strcpy(two, "foo");
714   (void) memccpy(two, one, 'q', 9);
715   equal(two, "hi there", 5);            /* Just paranoia. */
716   equal(one, "hi there", 6);            /* Stomped on source? */
717
718   (void) strcpy(one, "abcdefgh");
719   (void) strcpy(two, "horsefeathers");
720   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
721   equal(one, "abcdefgh", 8);            /* Source intact? */
722   equal(two, "abcdefeathers", 9);               /* Copy correct? */
723
724   (void) strcpy(one, "abcd");
725   (void) strcpy(two, "bumblebee");
726   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
727   equal(two, "aumblebee", 11);
728   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
729   equal(two, "abcdlebee", 13);
730   (void) strcpy(one, "xyz");
731   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
732   equal(two, "xbcdlebee", 15);
733
734   /* memset.  */
735   it = "memset";
736   (void) strcpy(one, "abcdefgh");
737   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
738   equal(one, "axxxefgh", 2);            /* Basic test. */
739
740   (void) memset(one+2, 'y', 0);
741   equal(one, "axxxefgh", 3);            /* Zero-length set. */
742
743   (void) memset(one+5, 0, 1);
744   equal(one, "axxxe", 4);                       /* Zero fill. */
745   equal(one+6, "gh", 5);                        /* And the leftover. */
746
747   (void) memset(one+2, 010045, 1);
748   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
749
750   /* Test for more complex versions of memset, for all alignments and
751      lengths up to 256. This test takes a little while, perhaps it should
752      be made weaker? */
753   {
754     char data[512];
755     int i;
756     int j;
757     int k;
758     int c;
759
760     for (i = 0; i < 512; i++)
761       data[i] = 'x';
762     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
763                                         memset(,'y',) */
764       for (j = 0; j < 256; j++)
765         for (i = 0; i < 256; i++)
766           {
767             memset(data+i,c,j);
768             for (k = 0; k < i; k++)
769               if (data[k] != 'x')
770                 goto fail;
771             for (k = i; k < i+j; k++)
772               {
773                 if (data[k] != c)
774                   goto fail;
775                 data[k] = 'x';
776               }
777             for (k = i+j; k < 512; k++)
778               if (data[k] != 'x')
779                 goto fail;
780             continue;
781
782           fail:
783             check(0,7+i+j*256+(c != 0)*256*256);
784           }
785   }
786
787   /* bcopy - much like memcpy.
788      Berklix manual is silent about overlap, so don't test it.  */
789   it = "bcopy";
790   (void) bcopy("abc", one, 4);
791   equal(one, "abc", 1);                 /* Simple copy. */
792
793   (void) strcpy(one, "abcdefgh");
794   (void) bcopy("xyz", one+1, 2);
795   equal(one, "axydefgh", 2);            /* Basic test. */
796
797   (void) strcpy(one, "abc");
798   (void) bcopy("xyz", one, 0);
799   equal(one, "abc", 3);                 /* Zero-length copy. */
800
801   (void) strcpy(one, "hi there");
802   (void) strcpy(two, "foo");
803   (void) bcopy(one, two, 9);
804   equal(two, "hi there", 4);            /* Just paranoia. */
805   equal(one, "hi there", 5);            /* Stomped on source? */
806
807   /* bzero.  */
808   it = "bzero";
809   (void) strcpy(one, "abcdef");
810   bzero(one+2, 2);
811   equal(one, "ab", 1);                  /* Basic test. */
812   equal(one+3, "", 2);
813   equal(one+4, "ef", 3);
814
815   (void) strcpy(one, "abcdef");
816   bzero(one+2, 0);
817   equal(one, "abcdef", 4);              /* Zero-length copy. */
818
819 #if 0
820   /* bcmp - somewhat like memcmp.  */
821   it = "bcmp";
822   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
823   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
824   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
825   check(bcmp("abce", "abcd", 4) != 0, 4);
826   check(bcmp("alph", "beta", 4) != 0, 5);
827   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
828   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
829 #endif
830
831   {
832     char text[] = "This,is,a,test";
833     char *list = text;
834     it = "strsep";
835     check (!strcmp ("This", strsep (&list, ",")), 1);
836     check (!strcmp ("is", strsep (&list, ",")), 2);
837     check (!strcmp ("a", strsep (&list, ",")), 3);
838     check (!strcmp ("test", strsep (&list, ",")), 4);
839     check (strsep (&list, ",") == NULL, 5);
840   }
841
842   /* strerror - VERY system-dependent.  */
843   {
844     int f;
845     it = "strerror";
846     f = __open("/", O_WRONLY);  /* Should always fail. */
847     check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
848     equal(strerror(errno), _sys_errlist[errno], 2);
849   }
850
851   {
852     int status;
853     if (errors == 0)
854       {
855         status = EXIT_SUCCESS;
856         puts("No errors.");
857       }
858     else
859       {
860         status = EXIT_FAILURE;
861         printf("%Zd errors.\n", errors);
862       }
863     exit(status);
864   }
865 }