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