OSDN Git Service

Attempt to clean up the strerror_r situation.
[uclinux-h8/uClibc.git] / libc / string / wstring.c
1 /*  Copyright (C) 2002     Manuel Novoa III
2  *
3  *  This library is free software; you can redistribute it and/or
4  *  modify it under the terms of the GNU Library General Public
5  *  License as published by the Free Software Foundation; either
6  *  version 2 of the License, or (at your option) any later version.
7  *
8  *  This library is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  *  Library General Public License for more details.
12  *
13  *  You should have received a copy of the GNU Library General Public
14  *  License along with this library; if not, write to the Free
15  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16  */
17
18 /*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
19  *
20  *  Besides uClibc, I'm using this code in my libc for elks, which is
21  *  a 16-bit environment with a fairly limited compiler.  It would make
22  *  things much easier for me if this file isn't modified unnecessarily.
23  *  In particular, please put any new or replacement functions somewhere
24  *  else, and modify the makefile to use your version instead.
25  *  Thanks.  Manuel
26  *
27  *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
28
29 #define _STDIO_UTILITY
30 #define _GNU_SOURCE
31 #include <string.h>
32 #include <strings.h>
33 #include <stdio.h>
34 #include <limits.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <errno.h>
38
39 #ifdef WANT_WIDE
40 #include <wchar.h>
41 #include <wctype.h>
42 #include <locale.h>
43
44 #define Wvoid                   wchar_t
45 #define Wchar                   wchar_t
46 #define Wuchar                  __uwchar_t
47 #define Wint                    wchar_t
48
49 #else
50
51 #define Wvoid                   void
52 #define Wchar                   char
53 typedef unsigned char   __string_uchar_t;
54 #define Wuchar                  __string_uchar_t
55 #define Wint                    int
56
57 #endif
58
59 /**********************************************************************/
60 /* NOTE: If we ever do internationalized syserr messages, this will
61  * have to be changed! */
62
63 #if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14
64 #define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14)
65 #else
66 #define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN
67 #endif
68
69 #define _SYS_NERR               125
70 #define _SYS_ERRMSG_MAXLEN       50
71
72 extern const char _string_syserrmsgs[];
73
74 /**********************************************************************/
75 #ifdef L__string_syserrmsgs
76
77 const char _string_syserrmsgs[] = {
78         /*   0:    0,  8 */ "Success\0"
79         /*   1:    8, 24 */ "Operation not permitted\0"
80         /*   2:   32, 26 */ "No such file or directory\0"
81         /*   3:   58, 16 */ "No such process\0"
82         /*   4:   74, 24 */ "Interrupted system call\0"
83         /*   5:   98, 19 */ "Input/output error\0"
84         /*   6:  117, 26 */ "No such device or address\0"
85         /*   7:  143, 23 */ "Argument list too long\0"
86         /*   8:  166, 18 */ "Exec format error\0"
87         /*   9:  184, 20 */ "Bad file descriptor\0"
88         /*  10:  204, 19 */ "No child processes\0"
89         /*  11:  223, 33 */ "Resource temporarily unavailable\0"
90         /*  12:  256, 23 */ "Cannot allocate memory\0"
91         /*  13:  279, 18 */ "Permission denied\0"
92         /*  14:  297, 12 */ "Bad address\0"
93         /*  15:  309, 22 */ "Block device required\0"
94         /*  16:  331, 24 */ "Device or resource busy\0"
95         /*  17:  355, 12 */ "File exists\0"
96         /*  18:  367, 26 */ "Invalid cross-device link\0"
97         /*  19:  393, 15 */ "No such device\0"
98         /*  20:  408, 16 */ "Not a directory\0"
99         /*  21:  424, 15 */ "Is a directory\0"
100         /*  22:  439, 17 */ "Invalid argument\0"
101         /*  23:  456, 30 */ "Too many open files in system\0"
102         /*  24:  486, 20 */ "Too many open files\0"
103         /*  25:  506, 31 */ "Inappropriate ioctl for device\0"
104         /*  26:  537, 15 */ "Text file busy\0"
105         /*  27:  552, 15 */ "File too large\0"
106         /*  28:  567, 24 */ "No space left on device\0"
107         /*  29:  591, 13 */ "Illegal seek\0"
108         /*  30:  604, 22 */ "Read-only file system\0"
109         /*  31:  626, 15 */ "Too many links\0"
110         /*  32:  641, 12 */ "Broken pipe\0"
111         /*  33:  653, 33 */ "Numerical argument out of domain\0"
112         /*  34:  686, 30 */ "Numerical result out of range\0"
113         /*  35:  716, 26 */ "Resource deadlock avoided\0"
114         /*  36:  742, 19 */ "File name too long\0"
115         /*  37:  761, 19 */ "No locks available\0"
116         /*  38:  780, 25 */ "Function not implemented\0"
117         /*  39:  805, 20 */ "Directory not empty\0"
118         /*  40:  825, 34 */ "Too many levels of symbolic links\0"
119         /*  41:  859,  1 */ "\0"
120         /*  42:  860, 27 */ "No message of desired type\0"
121         /*  43:  887, 19 */ "Identifier removed\0"
122         /*  44:  906, 28 */ "Channel number out of range\0"
123         /*  45:  934, 25 */ "Level 2 not synchronized\0"
124         /*  46:  959, 15 */ "Level 3 halted\0"
125         /*  47:  974, 14 */ "Level 3 reset\0"
126         /*  48:  988, 25 */ "Link number out of range\0"
127         /*  49: 1013, 29 */ "Protocol driver not attached\0"
128         /*  50: 1042, 27 */ "No CSI structure available\0"
129         /*  51: 1069, 15 */ "Level 2 halted\0"
130         /*  52: 1084, 17 */ "Invalid exchange\0"
131         /*  53: 1101, 27 */ "Invalid request descriptor\0"
132         /*  54: 1128, 14 */ "Exchange full\0"
133         /*  55: 1142,  9 */ "No anode\0"
134         /*  56: 1151, 21 */ "Invalid request code\0"
135         /*  57: 1172, 13 */ "Invalid slot\0"
136         /*  58: 1185,  1 */ "\0"
137         /*  59: 1186, 21 */ "Bad font file format\0"
138         /*  60: 1207, 20 */ "Device not a stream\0"
139         /*  61: 1227, 18 */ "No data available\0"
140         /*  62: 1245, 14 */ "Timer expired\0"
141         /*  63: 1259, 25 */ "Out of streams resources\0"
142         /*  64: 1284, 30 */ "Machine is not on the network\0"
143         /*  65: 1314, 22 */ "Package not installed\0"
144         /*  66: 1336, 17 */ "Object is remote\0"
145         /*  67: 1353, 22 */ "Link has been severed\0"
146         /*  68: 1375, 16 */ "Advertise error\0"
147         /*  69: 1391, 14 */ "Srmount error\0"
148         /*  70: 1405, 28 */ "Communication error on send\0"
149         /*  71: 1433, 15 */ "Protocol error\0"
150         /*  72: 1448, 19 */ "Multihop attempted\0"
151         /*  73: 1467, 19 */ "RFS specific error\0"
152         /*  74: 1486, 12 */ "Bad message\0"
153         /*  75: 1498, 38 */ "Value too large for defined data type\0"
154         /*  76: 1536, 27 */ "Name not unique on network\0"
155         /*  77: 1563, 29 */ "File descriptor in bad state\0"
156         /*  78: 1592, 23 */ "Remote address changed\0"
157         /*  79: 1615, 39 */ "Can not access a needed shared library\0"
158         /*  80: 1654, 37 */ "Accessing a corrupted shared library\0"
159         /*  81: 1691, 32 */ ".lib section in a.out corrupted\0"
160         /*  82: 1723, 48 */ "Attempting to link in too many shared libraries\0"
161         /*  83: 1771, 38 */ "Cannot exec a shared library directly\0"
162         /*  84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0"
163         /*  85: 1859, 44 */ "Interrupted system call should be restarted\0"
164         /*  86: 1903, 19 */ "Streams pipe error\0"
165         /*  87: 1922, 15 */ "Too many users\0"
166         /*  88: 1937, 31 */ "Socket operation on non-socket\0"
167         /*  89: 1968, 29 */ "Destination address required\0"
168         /*  90: 1997, 17 */ "Message too long\0"
169         /*  91: 2014, 31 */ "Protocol wrong type for socket\0"
170         /*  92: 2045, 23 */ "Protocol not available\0"
171         /*  93: 2068, 23 */ "Protocol not supported\0"
172         /*  94: 2091, 26 */ "Socket type not supported\0"
173         /*  95: 2117, 24 */ "Operation not supported\0"
174         /*  96: 2141, 30 */ "Protocol family not supported\0"
175         /*  97: 2171, 41 */ "Address family not supported by protocol\0"
176         /*  98: 2212, 23 */ "Address already in use\0"
177         /*  99: 2235, 32 */ "Cannot assign requested address\0"
178         /* 100: 2267, 16 */ "Network is down\0"
179         /* 101: 2283, 23 */ "Network is unreachable\0"
180         /* 102: 2306, 36 */ "Network dropped connection on reset\0"
181         /* 103: 2342, 33 */ "Software caused connection abort\0"
182         /* 104: 2375, 25 */ "Connection reset by peer\0"
183         /* 105: 2400, 26 */ "No buffer space available\0"
184         /* 106: 2426, 40 */ "Transport endpoint is already connected\0"
185         /* 107: 2466, 36 */ "Transport endpoint is not connected\0"
186         /* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0"
187         /* 109: 2548, 35 */ "Too many references: cannot splice\0"
188         /* 110: 2583, 21 */ "Connection timed out\0"
189         /* 111: 2604, 19 */ "Connection refused\0"
190         /* 112: 2623, 13 */ "Host is down\0"
191         /* 113: 2636, 17 */ "No route to host\0"
192         /* 114: 2653, 30 */ "Operation already in progress\0"
193         /* 115: 2683, 26 */ "Operation now in progress\0"
194         /* 116: 2709, 22 */ "Stale NFS file handle\0"
195         /* 117: 2731, 25 */ "Structure needs cleaning\0"
196         /* 118: 2756, 28 */ "Not a XENIX named type file\0"
197         /* 119: 2784, 30 */ "No XENIX semaphores available\0"
198         /* 120: 2814, 21 */ "Is a named type file\0"
199         /* 121: 2835, 17 */ "Remote I/O error\0"
200         /* 122: 2852, 20 */ "Disk quota exceeded\0"
201         /* 123: 2872, 16 */ "No medium found\0"
202         /* 124: 2888, 18 */ "Wrong medium type"
203 };
204
205 #endif
206 /**********************************************************************/
207 #ifdef L_sys_errlist
208
209 link_warning(_sys_errlist, "sys_nerr and sys_errlist are obsolete and uClibc support for them (in at least some configurations) will probably be unavailable in the near future.")
210
211 int sys_nerr = _SYS_NERR;
212
213 const char *const sys_errlist[] = {
214         _string_syserrmsgs + 0,
215         _string_syserrmsgs + 8,
216         _string_syserrmsgs + 32,
217         _string_syserrmsgs + 58,
218         _string_syserrmsgs + 74,
219         _string_syserrmsgs + 98,
220         _string_syserrmsgs + 117,
221         _string_syserrmsgs + 143,
222         _string_syserrmsgs + 166,
223         _string_syserrmsgs + 184,
224         _string_syserrmsgs + 204,
225         _string_syserrmsgs + 223,
226         _string_syserrmsgs + 256,
227         _string_syserrmsgs + 279,
228         _string_syserrmsgs + 297,
229         _string_syserrmsgs + 309,
230         _string_syserrmsgs + 331,
231         _string_syserrmsgs + 355,
232         _string_syserrmsgs + 367,
233         _string_syserrmsgs + 393,
234         _string_syserrmsgs + 408,
235         _string_syserrmsgs + 424,
236         _string_syserrmsgs + 439,
237         _string_syserrmsgs + 456,
238         _string_syserrmsgs + 486,
239         _string_syserrmsgs + 506,
240         _string_syserrmsgs + 537,
241         _string_syserrmsgs + 552,
242         _string_syserrmsgs + 567,
243         _string_syserrmsgs + 591,
244         _string_syserrmsgs + 604,
245         _string_syserrmsgs + 626,
246         _string_syserrmsgs + 641,
247         _string_syserrmsgs + 653,
248         _string_syserrmsgs + 686,
249         _string_syserrmsgs + 716,
250         _string_syserrmsgs + 742,
251         _string_syserrmsgs + 761,
252         _string_syserrmsgs + 780,
253         _string_syserrmsgs + 805,
254         _string_syserrmsgs + 825,
255         /*      _string_syserrmsgs + 859, */
256         NULL,                                           /* glibc compatiblity :-( */
257         _string_syserrmsgs + 860,
258         _string_syserrmsgs + 887,
259         _string_syserrmsgs + 906,
260         _string_syserrmsgs + 934,
261         _string_syserrmsgs + 959,
262         _string_syserrmsgs + 974,
263         _string_syserrmsgs + 988,
264         _string_syserrmsgs + 1013,
265         _string_syserrmsgs + 1042,
266         _string_syserrmsgs + 1069,
267         _string_syserrmsgs + 1084,
268         _string_syserrmsgs + 1101,
269         _string_syserrmsgs + 1128,
270         _string_syserrmsgs + 1142,
271         _string_syserrmsgs + 1151,
272         _string_syserrmsgs + 1172,
273         /*      _string_syserrmsgs + 1185, */
274         NULL,                                           /* glibc compatiblity :-( */
275         _string_syserrmsgs + 1186,
276         _string_syserrmsgs + 1207,
277         _string_syserrmsgs + 1227,
278         _string_syserrmsgs + 1245,
279         _string_syserrmsgs + 1259,
280         _string_syserrmsgs + 1284,
281         _string_syserrmsgs + 1314,
282         _string_syserrmsgs + 1336,
283         _string_syserrmsgs + 1353,
284         _string_syserrmsgs + 1375,
285         _string_syserrmsgs + 1391,
286         _string_syserrmsgs + 1405,
287         _string_syserrmsgs + 1433,
288         _string_syserrmsgs + 1448,
289         _string_syserrmsgs + 1467,
290         _string_syserrmsgs + 1486,
291         _string_syserrmsgs + 1498,
292         _string_syserrmsgs + 1536,
293         _string_syserrmsgs + 1563,
294         _string_syserrmsgs + 1592,
295         _string_syserrmsgs + 1615,
296         _string_syserrmsgs + 1654,
297         _string_syserrmsgs + 1691,
298         _string_syserrmsgs + 1723,
299         _string_syserrmsgs + 1771,
300         _string_syserrmsgs + 1809,
301         _string_syserrmsgs + 1859,
302         _string_syserrmsgs + 1903,
303         _string_syserrmsgs + 1922,
304         _string_syserrmsgs + 1937,
305         _string_syserrmsgs + 1968,
306         _string_syserrmsgs + 1997,
307         _string_syserrmsgs + 2014,
308         _string_syserrmsgs + 2045,
309         _string_syserrmsgs + 2068,
310         _string_syserrmsgs + 2091,
311         _string_syserrmsgs + 2117,
312         _string_syserrmsgs + 2141,
313         _string_syserrmsgs + 2171,
314         _string_syserrmsgs + 2212,
315         _string_syserrmsgs + 2235,
316         _string_syserrmsgs + 2267,
317         _string_syserrmsgs + 2283,
318         _string_syserrmsgs + 2306,
319         _string_syserrmsgs + 2342,
320         _string_syserrmsgs + 2375,
321         _string_syserrmsgs + 2400,
322         _string_syserrmsgs + 2426,
323         _string_syserrmsgs + 2466,
324         _string_syserrmsgs + 2502,
325         _string_syserrmsgs + 2548,
326         _string_syserrmsgs + 2583,
327         _string_syserrmsgs + 2604,
328         _string_syserrmsgs + 2623,
329         _string_syserrmsgs + 2636,
330         _string_syserrmsgs + 2653,
331         _string_syserrmsgs + 2683,
332         _string_syserrmsgs + 2709,
333         _string_syserrmsgs + 2731,
334         _string_syserrmsgs + 2756,
335         _string_syserrmsgs + 2784,
336         _string_syserrmsgs + 2814,
337         _string_syserrmsgs + 2835,
338         _string_syserrmsgs + 2852,
339         _string_syserrmsgs + 2872,
340         _string_syserrmsgs + 2888,
341 };
342
343 #endif
344 /**********************************************************************/
345 #ifdef L_wmemcpy
346 #define L_memcpy
347 #define Wmemcpy wmemcpy
348 #else
349 #define Wmemcpy memcpy
350 #endif
351
352 #ifdef L_memcpy
353
354 Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
355 {
356         register Wchar *r1 = s1;
357         register const Wchar *r2 = s2;
358
359 #ifdef __BCC__
360         while (n--) {
361                 *r1++ = *r2++;
362         }
363 #else
364         while (n) {
365                 *r1++ = *r2++;
366                 --n;
367         }
368 #endif
369
370         return s1;
371 }
372
373 #endif
374 /**********************************************************************/
375 #ifdef L_wmemmove
376 #define L_memmove
377 #define Wmemmove wmemmove
378 #else
379 #define Wmemmove memmove
380 #endif
381
382 #ifdef L_memmove
383
384 Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n)
385 {
386 #ifdef __BCC__
387         register Wchar *s = (Wchar *) s1;
388         register const Wchar *p = (const Wchar *) s2;
389
390         if (p >= s) {
391                 while (n--) {
392                         *s++ = *p++;
393                 }
394         } else {
395                 s += n;
396                 p += n;
397                 while (n--) {
398                         *--s = *--p;
399                 }
400         }
401
402         return s1;
403 #else
404         register Wchar *s = (Wchar *) s1;
405         register const Wchar *p = (const Wchar *) s2;
406
407         if (p >= s) {
408                 while (n) {
409                         *s++ = *p++;
410                         --n;
411                 }
412         } else {
413                 while (n) {
414                         --n;
415                         s[n] = p[n];
416                 }
417         }
418
419         return s1;
420 #endif
421 }
422
423 #endif
424 /**********************************************************************/
425 #ifdef L_wcscpy
426 #define L_strcpy
427 #define Wstrcpy wcscpy
428 #else
429 #define Wstrcpy strcpy
430 #endif
431
432 #ifdef L_strcpy
433
434 Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2)
435 {
436         register Wchar *s = s1;
437
438 #ifdef __BCC__
439         do {
440                 *s = *s2++;
441         } while (*s++ != 0);
442 #else
443         while ( (*s++ = *s2++) != 0 );
444 #endif
445
446         return s1;
447 }
448
449 #endif
450 /**********************************************************************/
451 #ifdef L_wcsncpy
452 #define L_strncpy
453 #define Wstrncpy wcsncpy
454 #else
455 #define Wstrncpy strncpy
456 #endif
457
458 #ifdef L_strncpy
459
460 Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2,
461                                 size_t n)
462 {
463         register Wchar *s = s1;
464
465 #ifdef __BCC__
466         while (n--) {
467                 if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
468                 ++s;
469         }
470 #else
471         while (n) {
472                 if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
473                 ++s;
474                 --n;
475         }
476 #endif
477         
478         return s1;
479 }
480
481 #endif
482 /**********************************************************************/
483 #ifdef L_wcscat
484 #define L_strcat
485 #define Wstrcat wcscat
486 #else
487 #define Wstrcat strcat
488 #endif
489
490 #ifdef L_strcat
491
492 Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2)
493 {
494         register Wchar *s = s1;
495
496         while (*s++);
497         --s;
498         while ((*s++ = *s2++) != 0);
499
500         return s1;
501 }
502
503 #endif
504 /**********************************************************************/
505 #ifdef L_wcsncat
506 #define L_strncat
507 #define Wstrncat wcsncat
508 #else
509 #define Wstrncat strncat
510 #endif
511
512 #ifdef L_strncat
513
514 Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2,
515                                 size_t n)
516 {
517         register Wchar *s = s1;
518
519         while (*s++);
520         --s;
521 #if __BCC__
522         while (n-- && ((*s = *s2++) != 0)) ++s;
523 #else
524         while (n && ((*s = *s2++) != 0)) {
525                 --n;
526                 ++s;
527         }
528 #endif
529         *s = 0;
530
531         return s1;
532 }
533
534 #endif
535 /**********************************************************************/
536 #ifdef L_wmemcmp
537 #define L_memcmp
538 #define Wmemcmp wmemcmp
539 #else
540 #define Wmemcmp memcmp
541 #endif
542
543 #ifdef L_memcmp
544
545 #ifndef L_wmemcmp
546 weak_alias(memcmp,bcmp);
547 #endif
548
549 int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
550 {
551         register const Wuchar *r1 = (const Wuchar *) s1;
552         register const Wuchar *r2 = (const Wuchar *) s2;
553
554 #ifdef WANT_WIDE
555         while (n && (*r1 == *r2)) {
556                 ++r1;
557                 ++r2;
558                 --n;
559         }
560
561         return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1);
562 #else
563         int r = 0;
564
565         while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0));
566
567         return r;
568 #endif
569 }
570
571 #endif
572 /**********************************************************************/
573 #ifdef L_wcscmp
574 #define L_strcmp
575 #define Wstrcmp wcscmp
576 #else
577 #define Wstrcmp strcmp
578 #endif
579
580 #ifdef L_strcmp
581
582 #ifndef L_wcscmp
583 #warning implement strcoll and remove weak alias (or enable for C locale only)
584 weak_alias(strcmp,strcoll);
585 #endif
586
587 int Wstrcmp(register const Wchar *s1, register const Wchar *s2)
588 {
589 #ifdef WANT_WIDE
590         while (*((Wuchar *)s1) == *((Wuchar *)s2)) {
591                 if (!*s1++) {
592                         return 0;
593                 }
594                 ++s2;
595         }
596
597         return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1;
598 #else
599         int r;
600
601         while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++))
602                         == 0) && *s1++);
603         
604         return r;
605 #endif
606 }
607 #endif
608 /**********************************************************************/
609 #ifdef L_strcoll
610 #error implement strcoll and remove weak_alias!!
611
612 #if 0
613 extern unsigned char *_ctype_collate;
614 int strcoll(register const char *s1, const char *s2)
615 {
616     int r;
617
618     while (!(r = (_ctype_collate[(int)(*s1++)]-_ctype_collate[(int)(*s2++)])));
619
620     return r;
621 }
622 #endif
623
624 #endif
625 /**********************************************************************/
626 #ifdef L_wcsncmp
627 #define L_strncmp
628 #define Wstrncmp wcsncmp
629 #else
630 #define Wstrncmp strncmp
631 #endif
632
633 #ifdef L_strncmp
634
635 int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n)
636 {
637 #ifdef WANT_WIDE
638         while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) {
639                 if (!*s1++) {
640                         return 0;
641                 }
642                 ++s2;
643                 --n;
644         }
645
646         return (n == 0) ? 0 : ((*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1);
647 #else
648         int r = 0;
649
650         while (n--
651                    && ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++))
652                         == 0)
653                    && *s1++);
654
655         return r;
656 #endif
657 }
658
659 #endif
660 /**********************************************************************/
661 #ifdef L_strxfrm
662 #error implement strxfrm
663 /* size_t strxfrm(char *dst, const char *src, size_t len); */
664 #endif  
665 /**********************************************************************/
666 #ifdef L_wmemchr
667 #define L_memchr
668 #define Wmemchr wmemchr
669 #else
670 #define Wmemchr memchr
671 #endif
672
673 #ifdef L_memchr
674
675 Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n)
676 {
677         register const Wuchar *r = (const Wuchar *) s;
678 #ifdef __BCC__
679         /* bcc can optimize the counter if it thinks it is a pointer... */
680         register const char *np = (const char *) n;
681 #else
682 #define np n
683 #endif
684
685         while (np) {
686                 if (*r == ((Wuchar)c)) {
687                         return (Wvoid *) r;     /* silence the warning */
688                 }
689                 ++r;
690                 --np;
691         }
692
693         return NULL;
694 }
695 #undef np
696
697 #endif
698 /**********************************************************************/
699 #ifdef L_wcschr
700 #define L_strchr
701 #define Wstrchr wcschr
702 #else
703 #define Wstrchr strchr
704 #endif
705
706 #ifdef L_strchr
707
708 #ifndef L_wcschr
709 weak_alias(strchr,index);
710 #endif
711
712 Wchar *Wstrchr(register const Wchar *s, Wint c)
713 {
714         do {
715                 if (*s == ((Wchar)c)) {
716                         return (Wchar *) s;     /* silence the warning */
717                 }
718         } while (*s++);
719
720         return NULL;
721 }
722
723 #endif
724 /**********************************************************************/
725 #ifdef L_wcscspn
726 #define L_strcspn
727 #define Wstrcspn wcscspn
728 #else
729 #define Wstrcspn strcspn
730 #endif
731
732 #ifdef L_strcspn
733
734 size_t Wstrcspn(const Wchar *s1, const Wchar *s2)
735 {
736         register const Wchar *s;
737         register const Wchar *p;
738
739         for ( s=s1 ; *s ; s++ ) {
740                 for ( p=s2 ; *p ; p++ ) {
741                         if (*p == *s) goto done;
742                 }
743         }
744  done:
745         return s - s1;
746 }
747
748 #endif
749 /**********************************************************************/
750 #ifdef L_wcspbrk
751 #define L_strpbrk
752 #define Wstrpbrk wcspbrk
753 #else
754 #define Wstrpbrk strpbrk
755 #endif
756
757 #ifdef L_strpbrk
758
759 Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2)
760 {
761         register const Wchar *s;
762         register const Wchar *p;
763
764         for ( s=s1 ; *s ; s++ ) {
765                 for ( p=s2 ; *p ; p++ ) {
766                         if (*p == *s) return (Wchar *) s; /* silence the warning */
767                 }
768         }
769         return NULL;
770 }
771 #endif
772 /**********************************************************************/
773 #ifdef L_wcsrchr
774 #define L_strrchr
775 #define Wstrrchr wcsrchr
776 #else
777 #define Wstrrchr strrchr
778 #endif
779
780 #ifdef L_strrchr
781
782 #ifndef L_wcsrchr
783 weak_alias(strrchr,rindex);
784 #endif
785
786 Wchar *Wstrrchr(register const  Wchar *s, Wint c)
787 {
788         register const Wchar *p;
789
790         p = NULL;
791         do {
792                 if (*s == (Wchar) c) {
793                         p = s;
794                 }
795         } while (*s++);
796
797         return (Wchar *) p;                     /* silence the warning */
798 }
799
800 #endif
801 /**********************************************************************/
802 #ifdef L_wcsspn
803 #define L_strspn
804 #define Wstrspn wcsspn
805 #else
806 #define Wstrspn strspn
807 #endif
808
809 #ifdef L_strspn
810
811 size_t Wstrspn(const Wchar *s1, const Wchar *s2)
812 {
813         register const Wchar *s = s1;
814         register const Wchar *p = s2;
815
816         while (*p) {
817                 if (*p++ == *s) {
818                         ++s;
819                         p = s2;
820                 }
821         }
822         return s - s1;
823 }
824
825 #endif
826 /**********************************************************************/
827 #ifdef L_wcsstr
828 #define L_strstr
829 #define Wstrstr wcsstr
830 #else
831 #define Wstrstr strstr
832 #endif
833
834 #ifdef L_strstr
835
836 /* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */
837
838 #ifdef L_wcsstr
839 weak_alias(wcsstr,wcswcs);
840 #endif
841
842 Wchar *Wstrstr(const Wchar *s1, const Wchar *s2)
843 {
844         register const Wchar *s = s1;
845         register const Wchar *p = s2;
846
847         do {
848                 if (!*p) {
849                         return (Wchar *) s1;;
850                 }
851                 if (*p == *s) {
852                         ++p;
853                         ++s;
854                 } else {
855                         p = s2;
856                         if (!*s) {
857                                 return NULL;
858                         }
859                         s = ++s1;
860                 }
861         } while (1);
862 }
863
864 #endif
865 /**********************************************************************/
866 #ifdef L_wcstok
867 #define L_strtok_r
868 #define Wstrtok_r wcstok
869 #define Wstrspn wcsspn
870 #define Wstrpbrk wcspbrk
871 #else
872 #define Wstrtok_r strtok_r
873 #define Wstrspn strspn
874 #define Wstrpbrk strpbrk
875 #endif
876
877 #ifdef L_strtok_r
878
879 Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2,
880                                  Wchar ** __restrict next_start)
881 {
882         register Wchar *s;
883         register Wchar *p;
884
885 #if 1
886         if (((s = s1) != NULL) || ((s = *next_start) != NULL)) {
887                 if (*(s += Wstrspn(s, s2))) {
888                         if ((p = Wstrpbrk(s, s2)) != NULL) {
889                                 *p++ = 0;
890                         }
891                 } else {
892                         p = s = NULL;
893                 }
894                 *next_start = p;
895         }
896         return s;
897 #else
898         if (!(s = s1)) {
899                 s = *next_start;
900         }
901         if (s && *(s += Wstrspn(s, s2))) {
902                 if (*(p = s + Wstrcspn(s, s2))) {
903                         *p++ = 0;
904                 }
905                 *next_start = p;
906                 return s;
907         }
908         return NULL;                            /* TODO: set *next_start = NULL for safety? */
909 #endif
910 }
911
912 #endif
913 /**********************************************************************/
914 /*  #ifdef L_wcstok */
915 /*  #define L_strtok */
916 /*  #define Wstrtok wcstok */
917 /*  #define Wstrtok_r wcstok_r */
918 /*  #else */
919 /*  #define Wstrtok strtok */
920 /*  #define Wstrtok_r strtok_r */
921 /*  #endif */
922
923 #ifdef L_strtok
924 #define Wstrtok strtok
925 #define Wstrtok_r strtok_r
926
927 Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2)
928 {
929         static Wchar *next_start;       /* Initialized to 0 since in bss. */
930         return Wstrtok_r(s1, s2, &next_start);
931 }
932
933 #endif
934 /**********************************************************************/
935 #ifdef L_wmemset
936 #define L_memset
937 #define Wmemset wmemset
938 #else
939 #define Wmemset memset
940 #endif
941
942 #ifdef L_memset
943
944 Wvoid *Wmemset(Wvoid *s, Wint c, size_t n)
945 {
946         register Wuchar *p = (Wuchar *) s;
947 #ifdef __BCC__
948         /* bcc can optimize the counter if it thinks it is a pointer... */
949         register const char *np = (const char *) n;
950 #else
951 #define np n
952 #endif
953
954         while (np) {
955                 *p++ = (Wuchar) c;
956                 --np;
957         }
958
959         return s;
960 }
961 #undef np
962
963 #endif
964 /**********************************************************************/
965 #ifdef L_wcslen
966 #define L_strlen
967 #define Wstrlen wcslen
968 #else
969 #define Wstrlen strlen
970 #endif
971
972 #ifdef L_strlen
973
974 size_t Wstrlen(const Wchar *s)
975 {
976         register const Wchar *p;
977
978         for (p=s ; *p ; p++);
979
980         return p - s;
981 }
982
983 #endif
984 /**********************************************************************/
985 /* ANSI/ISO end here */
986 /**********************************************************************/
987 #ifdef L_ffs
988
989 int ffs(int i)
990 {
991 #if 1
992         /* inlined binary search method */
993         char n = 1;
994 #if UINT_MAX == 0xffffU
995         /* nothing to do here -- just trying to avoiding possible problems */
996 #elif UINT_MAX == 0xffffffffU
997         if (!(i & 0xffff)) {
998                 n += 16;
999                 i >>= 16;
1000         }
1001 #else
1002 #error ffs needs rewriting!
1003 #endif
1004
1005         if (!(i & 0xff)) {
1006                 n += 8;
1007                 i >>= 8;
1008         }
1009         if (!(i & 0x0f)) {
1010                 n += 4;
1011                 i >>= 4;
1012         }
1013         if (!(i & 0x03)) {
1014                 n += 2;
1015                 i >>= 2;
1016         }
1017         return (i) ? (n + ((i+1) & 0x01)) : 0;
1018
1019 #else
1020         /* linear search -- slow, but small */
1021         int n;
1022
1023         for (n = 0 ; i ; ++n) {
1024                 i >>= 1;
1025         }
1026         
1027         return n;
1028 #endif
1029 }
1030
1031 #endif
1032 /**********************************************************************/
1033 #ifdef L_wcscasecmp
1034 #define L_strcasecmp
1035 #define Wstrcasecmp wcscasecmp
1036 #else
1037 #define Wstrcasecmp strcasecmp
1038 #endif
1039
1040 #ifdef L_strcasecmp
1041
1042 int Wstrcasecmp(register const Wchar *s1, register const Wchar *s2)
1043 {
1044 #ifdef WANT_WIDE
1045         while ((*s1 == *s2) || (towlower(*s1) == towlower(*s2))) {
1046                 if (!*s1++) {
1047                         return 0;
1048                 }
1049                 ++s2;
1050         }
1051
1052         return (((Wuchar)towlower(*s1)) < ((Wuchar)towlower(*s2))) ? -1 : 1;
1053         /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
1054 #else
1055         int r = 0;
1056
1057         while ( ((s1 == s2) ||
1058                          !(r = ((int)( tolower(*((Wuchar *)s1))))
1059                            - tolower(*((Wuchar *)s2))))
1060                         && (++s2, *s1++));
1061
1062         return r;
1063 #endif
1064 }
1065
1066 #endif
1067 /**********************************************************************/
1068 #ifdef L_wcsncasecmp
1069 #define L_strncasecmp
1070 #define Wstrncasecmp wcsncasecmp
1071 #else
1072 #define Wstrncasecmp strncasecmp
1073 #endif
1074
1075 #ifdef L_strncasecmp
1076
1077 int Wstrncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n)
1078 {
1079 #ifdef WANT_WIDE
1080         while (n && ((*s1 == *s2) || (towlower(*s1) == towlower(*s2)))) {
1081                 if (!*s1++) {
1082                         return 0;
1083                 }
1084                 ++s2;
1085                 --n;
1086         }
1087
1088         return (n == 0)
1089                 ? 0
1090                 : ((((Wuchar)towlower(*s1)) < ((Wuchar)towlower(*s2))) ? -1 : 1);
1091         /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
1092 #else
1093         int r = 0;
1094
1095         while ( n
1096                         && ((s1 == s2) ||
1097                                 !(r = ((int)( tolower(*((unsigned char *)s1))))
1098                                   - tolower(*((unsigned char *)s2))))
1099                         && (--n, ++s2, *s1++));
1100         return r;
1101 #endif
1102 }
1103 #endif
1104 /**********************************************************************/
1105 #ifdef L_wcsnlen
1106 #define L_strnlen
1107 #define Wstrnlen wcsnlen
1108 #else
1109 #define Wstrnlen strnlen
1110 #endif
1111
1112 #ifdef L_strnlen
1113
1114 size_t Wstrnlen(const Wchar *s, size_t max)
1115 {
1116         register const Wchar *p = s;
1117 #ifdef __BCC__
1118         /* bcc can optimize the counter if it thinks it is a pointer... */
1119         register const char *maxp = (const char *) max;
1120 #else
1121 #define maxp max
1122 #endif
1123
1124         while (maxp && *p) {
1125                 ++p;
1126                 --maxp;
1127         }
1128
1129         return p - s;
1130 }
1131 #undef maxp
1132 #endif
1133 /**********************************************************************/
1134 /* No wide analog. */
1135
1136 #ifdef L_memccpy
1137
1138 void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n)
1139 {
1140         register char *r1 = s1;
1141         register const char *r2 = s2;
1142
1143         while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c)));
1144
1145         return (n == (size_t) -1) ? NULL : r1;
1146 }
1147
1148 #endif
1149 /**********************************************************************/
1150 #ifdef L_wcsdup
1151 #define L_strdup
1152 #define Wstrdup wcsdup
1153 #define Wstrlen wcslen
1154 #define Wstrcpy wcscpy
1155 #else
1156 #define Wstrdup strdup
1157 #define Wstrlen strlen
1158 #define Wstrcpy strcpy
1159 #endif
1160
1161 #ifdef L_strdup
1162
1163 Wchar *Wstrdup(register const Wchar *s1)
1164 {
1165         register Wchar *s;
1166
1167     if ((s = malloc((Wstrlen(s1) + 1) * sizeof(Wchar))) != NULL) {
1168                 Wstrcpy(s, s1);
1169         }
1170
1171         return s;
1172 }
1173
1174 #endif
1175 /**********************************************************************/
1176 #ifdef L_strerror
1177
1178 char *strerror(int errnum)
1179 {
1180     static char buf[_SYS_ERRMSG_MAXLEN];
1181
1182     return (_susv3_strerror_r(errnum, buf, sizeof(buf)) == 0) ? buf : NULL;
1183 }
1184
1185 #endif
1186 /**********************************************************************/
1187 /* SUSv3 functions. */
1188 /**********************************************************************/
1189 #ifdef L__susv3_strerror_r
1190
1191 int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
1192 {
1193     register char *s;
1194     int i, retval;
1195     char buf[_SYS_ERRMSG_MAXLEN];
1196     static const char unknown[14] = {
1197                 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
1198     };
1199
1200     retval = EINVAL;
1201
1202     if (((unsigned int) errnum) < _SYS_NERR) {
1203                 /* Trade time for space.  This function should rarely be called
1204                  * so rather than keeping an array of pointers for the different
1205                  * messages, just run through the buffer until we find the
1206                  * correct string. */
1207                 for (s = (char *) _string_syserrmsgs, i = errnum ; i ; ++s) {
1208                         if (!*s) {
1209                                 --i;
1210                         }
1211                 }
1212                 if (*s) {               /* Make sure we have an actual message. */
1213                         retval = 0;
1214                         goto GOT_MESG;
1215                 }
1216     }
1217
1218     s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
1219     memcpy(s, unknown, sizeof(unknown));
1220
1221  GOT_MESG:
1222     if (!strerrbuf) {           /* SUSv3  */
1223                 buflen = 0;
1224     }
1225     i = strlen(s) + 1;
1226     if (i > buflen) {
1227                 i = buflen;
1228                 retval = ERANGE;
1229     }
1230
1231     if (i) {
1232                 memcpy(strerrbuf, s, i);
1233                 strerrbuf[i-1] = 0;     /* In case buf was too small. */
1234     }
1235
1236     if (retval) {
1237                 __set_errno(retval);
1238     }
1239
1240     return retval;
1241 }
1242
1243 #endif
1244 /**********************************************************************/
1245 /* GNU extension functions. */
1246 /**********************************************************************/
1247 #ifdef L__glibc_strerror_r
1248
1249 weak_alias(_glibc_strerror_r,__strerror_r);
1250
1251 char *_glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen)
1252 {
1253     _susv3_strerror_r(errnum, strerrbuf, buflen);
1254
1255     return strerrbuf;
1256 }
1257
1258 #endif
1259 /**********************************************************************/
1260 #ifdef L_wmempcpy
1261 #define L_mempcpy
1262 #define Wmempcpy wmempcpy
1263 #else
1264 #define Wmempcpy mempcpy
1265 #endif
1266
1267 #ifdef L_mempcpy
1268
1269 #ifndef L_wmempcpy
1270 /* uClibc's old string implementation did this to cater to some app. */
1271 weak_alias(mempcpy,__mempcpy);
1272 #endif
1273
1274 Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
1275 {
1276         register Wchar *r1 = s1;
1277         register const Wchar *r2 = s2;
1278
1279 #ifdef __BCC__
1280         while (n--) {
1281                 *r1++ = *r2++;
1282         }
1283 #else
1284         while (n) {
1285                 *r1++ = *r2++;
1286                 --n;
1287         }
1288 #endif
1289
1290         return r1;
1291 }
1292
1293 #endif
1294 /**********************************************************************/
1295 #ifdef L_memrchr
1296
1297 void *memrchr(const void *s, int c, size_t n)
1298 {
1299         register const unsigned char *r;
1300 #ifdef __BCC__
1301         /* bcc can optimize the counter if it thinks it is a pointer... */
1302         register const char *np = (const char *) n;
1303 #else
1304 #define np n
1305 #endif
1306         
1307         r = ((unsigned char *)s) + ((size_t) np);
1308
1309         while (np) {
1310                 if (*--r == ((unsigned char)c)) {
1311                         return (void *) r;      /* silence the warning */
1312                 }
1313                 --np;
1314         }
1315
1316         return NULL;
1317 }
1318 #undef np
1319
1320 #endif
1321 /**********************************************************************/
1322 #ifdef L_wcpcpy
1323 #define L_stpcpy
1324 #define Wstpcpy wcpcpy
1325 #else
1326 #define Wstpcpy stpcpy
1327 #endif
1328
1329 #ifdef L_stpcpy
1330
1331 Wchar *Wstpcpy(register Wchar * __restrict s1, const Wchar * __restrict s2)
1332 {
1333 #ifdef __BCC__
1334         do {
1335                 *s1 = *s2++;
1336         } while (*s1++ != 0);
1337 #else
1338         while ( (*s1++ = *s2++) != 0 );
1339 #endif
1340
1341         return s1 - 1;
1342 }
1343
1344 #endif
1345 /**********************************************************************/
1346 #ifdef L_wcpncpy
1347 #define L_stpncpy
1348 #define Wstpncpy wcpncpy
1349 #else
1350 #define Wstpncpy stpncpy
1351 #endif
1352
1353 #ifdef L_stpncpy
1354
1355 Wchar *Wstpncpy(register Wchar * __restrict s1,
1356                                 register const Wchar * __restrict s2,
1357                                 size_t n)
1358 {
1359         Wchar *s = s1;
1360         const Wchar *p = s2;
1361
1362 #ifdef __BCC__
1363         while (n--) {
1364                 if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
1365                 ++s;
1366         }
1367         return s1 + (s2 - p);
1368 #else
1369         while (n) {
1370                 if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
1371                 ++s;
1372                 --n;
1373         }
1374         return s1 + (s2 - p);
1375 #endif
1376 }
1377
1378 #endif
1379 /**********************************************************************/
1380 #ifdef L_bzero
1381
1382 void bzero(void *s, size_t n)
1383 {
1384         register unsigned char *p = s;
1385 #ifdef __BCC__
1386         /* bcc can optimize the counter if it thinks it is a pointer... */
1387         register const char *np = (const char *) n;
1388 #else
1389 #define np n
1390 #endif
1391
1392         while (np) {
1393                 *p++ = 0;
1394                 --np;
1395         }
1396 }
1397 #undef np
1398
1399 #endif
1400 /**********************************************************************/
1401 #ifdef L_bcopy
1402
1403 void bcopy(const void *s2, void *s1, size_t n)
1404 {
1405 #if 1
1406         memmove(s1, s2, n);
1407 #else
1408 #ifdef __BCC__
1409         register char *s;
1410         register const char *p;
1411
1412         s = s1;
1413         p = s2;
1414         if (p >= s) {
1415                 while (n--) {
1416                         *s++ = *p++;
1417                 }
1418         } else {
1419                 s += n;
1420                 p += n;
1421                 while (n--) {
1422                         *--s = *--p;
1423                 }
1424         }
1425 #else
1426         register char *s;
1427         register const char *p;
1428
1429         s = s1;
1430         p = s2;
1431         if (p >= s) {
1432                 while (n) {
1433                         *s++ = *p++;
1434                         --n;
1435                 }
1436         } else {
1437                 while (n) {
1438                         --n;
1439                         s[n] = p[n];
1440                 }
1441         }
1442 #endif
1443 #endif
1444 }
1445
1446 #endif
1447 /**********************************************************************/
1448 #ifdef L_strcasestr
1449
1450 char *strcasestr(const char *s1, const char *s2)
1451 {
1452         register const char *s = s1;
1453         register const char *p = s2;
1454
1455 #if 1
1456         do {
1457                 if (!*p) {
1458                         return (char *) s1;;
1459                 }
1460                 if ((*p == *s)
1461                         || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
1462                         ) {
1463                         ++p;
1464                         ++s;
1465                 } else {
1466                         p = s2;
1467                         if (!*s) {
1468                                 return NULL;
1469                         }
1470                         s = ++s1;
1471                 }
1472         } while (1);
1473 #else
1474         while (*p && *s) {
1475                 if ((*p == *s)
1476                         || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
1477                         ) {
1478                         ++p;
1479                         ++s;
1480                 } else {
1481                         p = s2;
1482                         s = ++s1;
1483                 }
1484         }
1485
1486         return (*p) ? NULL : (char *) s1;
1487 #endif
1488 }
1489
1490 #endif
1491 /**********************************************************************/
1492 #ifdef L_strndup
1493
1494 char *strndup(register const char *s1, size_t n)
1495 {
1496         register char *s;
1497
1498         n = strnlen(s1,n);                      /* Avoid problems if s1 not nul-terminated. */
1499
1500     if ((s = malloc(n + 1)) != NULL) {
1501                 memcpy(s, s1, n);
1502                 s[n] = 0;
1503         }
1504
1505         return s;
1506 }
1507
1508 #endif
1509 /**********************************************************************/
1510 #ifdef L_strsep
1511
1512 char *strsep(char ** __restrict s1, const char * __restrict s2)
1513 {
1514         register char *s = *s1;
1515         register char *p;
1516
1517 #if 1
1518         p = NULL;
1519         if (s && *s && (p = strpbrk(s, s2))) {
1520                 *p++ = 0;
1521         }
1522 #else
1523         if (s && *s && *(p = s + strcspn(s, s2))) {
1524                 *p++ = 0;
1525         } else {
1526                 p = NULL;
1527         }
1528 #endif
1529         *s1 = p;
1530         return s;
1531 }
1532
1533 #endif
1534 /**********************************************************************/
1535 #ifdef L_wcschrnul
1536 #define L_strchrnul
1537 #define Wstrchrnul wcschrnul
1538 #else
1539 #define Wstrchrnul strchrnul
1540 #endif
1541
1542 #ifdef L_strchrnul
1543
1544 Wchar *Wstrchrnul(register const Wchar *s, Wint c)
1545 {
1546         --s;
1547         while (*++s && (*s != ((Wchar)c)));
1548         return (Wchar *) s;
1549 }
1550
1551 #endif
1552 /**********************************************************************/
1553 #ifdef L_rawmemchr
1554
1555 void *rawmemchr(const void *s, int c)
1556 {
1557         register const unsigned char *r = s;
1558
1559         while (*r != ((unsigned char)c)) ++r;
1560
1561         return (void *) r;      /* silence the warning */
1562 }
1563
1564 #endif
1565 /**********************************************************************/
1566 #ifdef L_basename
1567
1568 char *basename(const char *path)
1569 {
1570         register const char *s;
1571         register const char *p;
1572
1573         p = s = path;
1574
1575         while (*s) {
1576                 if (*s++ == '/') {
1577                         p = s;
1578                 }
1579         }
1580
1581         return (char *) p;
1582 }
1583
1584 #endif
1585 /**********************************************************************/
1586 #ifdef L___xpg_basename
1587
1588 char *__xpg_basename(register char *path)
1589 {
1590         static const char null_or_empty[] = ".";
1591         char *first;
1592         register char *last;
1593
1594         first = (char *) null_or_empty;
1595
1596         if (path && *path) {
1597                 first = path;
1598                 last = path - 1;
1599
1600                 do {
1601                         if ((*path != '/') && (path > ++last)) {
1602                                 last = first = path;
1603                         }
1604                 } while (*++path);
1605
1606                 if (*first == '/') {
1607                         last = first;
1608                 }
1609                 last[1] = 0;
1610         }
1611
1612         return first;
1613 }
1614
1615 #endif
1616 /**********************************************************************/
1617 #ifdef L_dirname
1618
1619 char *dirname(char *path)
1620 {
1621         static const char null_or_empty_or_noslash[] = ".";
1622         register char *s;
1623         register char *last;
1624         char *first;
1625
1626         last = s = path;
1627
1628         if (s != NULL) {
1629
1630         LOOP:
1631                 while (*s && (*s != '/')) ++s;
1632                 first = s;
1633                 while (*s == '/') ++s;
1634                 if (*s) {
1635                         last = first;
1636                         goto LOOP;
1637                 }
1638
1639                 if (last == path) {
1640                         if (*last != '/') {
1641                                 goto DOT;
1642                         }
1643                         if ((*++last == '/') && (last[1] == 0)) {
1644                                 ++last;
1645                         }
1646                 }
1647                 *last = 0;
1648                 return path;
1649         }
1650  DOT:
1651         return (char *) null_or_empty_or_noslash;
1652 }
1653
1654 #endif
1655 /**********************************************************************/
1656 #ifdef L_strlcat
1657
1658 /* OpenBSD function:
1659  * Append at most n-1-strlen(dst) chars from src to dst and nul-terminate dst.
1660  * Returns strlen(src) + strlen({original} dst), so truncation occurred if the
1661  * return val is >= n.
1662  * Note: If dst doesn't contain a nul in the first n chars, strlen(dst) is
1663  *       taken as n. */
1664
1665 size_t strlcat(register char *__restrict dst,
1666                            register const char *__restrict src,
1667                            size_t n)
1668 {
1669         size_t len;
1670         char dummy[1];
1671
1672         len = 0;
1673
1674         while (1) {
1675                 if (len >= n) {
1676                         dst = dummy;
1677                         break;
1678                 }
1679                 if (!*dst) {
1680                         break;
1681                 }
1682                 ++dst;
1683                 ++len;
1684         }
1685
1686         while ((*dst = *src) != 0) {
1687                 if (++len < n) {
1688                         ++dst;
1689                 }
1690                 ++src;
1691         }
1692
1693         return len;
1694 }
1695
1696 #endif
1697 /**********************************************************************/
1698 #ifdef L_strlcpy
1699
1700 /* OpenBSD function:
1701  * Copy at most n-1 chars from src to dst and nul-terminate dst.
1702  * Returns strlen(src), so truncation occurred if the return value is >= n. */
1703
1704 size_t strlcpy(register char *__restrict dst,
1705                            register const char *__restrict src,
1706                            size_t n)
1707 {
1708         const char *src0 = src;
1709         char dummy[1];
1710
1711         if (!n) {
1712                 dst = dummy;
1713         } else {
1714                 --n;
1715         }
1716
1717         while ((*dst = *src) != 0) {
1718                 if (n) {
1719                         --n;
1720                         ++dst;
1721                 }
1722                 ++src;
1723         }
1724
1725         return src - src0;
1726 }
1727
1728 #endif
1729 /**********************************************************************/