OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [linux/] [uClibc/] [libc/] [string/] [wstring.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*  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
/*  Dec 20, 2002
30
 *  Initial test implementation of strcoll, strxfrm, wcscoll, and wcsxfrm.
31
 *  The code needs to be cleaned up a good bit, but I'd like to see people
32
 *  test it out.
33
 *
34
 *  Sep 11, 2003
35
 *  Patch by Atsushi Nemoto <anemo@mba.ocn.ne.jp> to do arch-required
36
 *  mapping of signal strings (alpha, mips, hppa, sparc).
37
 */
38
 
39
#define _STDIO_UTILITY
40
#define _GNU_SOURCE
41
#include <string.h>
42
#include <strings.h>
43
#include <stdio.h>
44
#include <limits.h>
45
#include <ctype.h>
46
#include <stdlib.h>
47
#include <errno.h>
48
#include <signal.h>
49
#include <assert.h>
50
#include <locale.h>
51
 
52
#ifdef WANT_WIDE
53
#include <wchar.h>
54
#include <wctype.h>
55
#include <bits/uClibc_uwchar.h>
56
 
57
#define Wvoid                   wchar_t
58
#define Wchar                   wchar_t
59
#define Wuchar                  __uwchar_t
60
#define Wint                    wchar_t
61
 
62
#else
63
 
64
#define Wvoid                   void
65
#define Wchar                   char
66
typedef unsigned char   __string_uchar_t;
67
#define Wuchar                  __string_uchar_t
68
#define Wint                    int
69
 
70
#endif
71
 
72
/**********************************************************************/
73
/* NOTE: If we ever do internationalized syserr messages, this will
74
 * have to be changed! */
75
 
76
#define _SYS_NERR                       125
77
#if defined(__mips__) || defined(__sparc__)
78
/* sparce and mips have an extra error entry, as EDEADLK and EDEADLOCK have
79
 * different meanings on those platforms. */
80
#undef _SYS_NERR
81
#define _SYS_NERR                       126
82
#endif
83
 
84
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
85
#define _SYS_ERRMSG_MAXLEN       50
86
#else  /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
87
#define _SYS_ERRMSG_MAXLEN       0
88
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
89
 
90
 
91
extern const char _string_syserrmsgs[];
92
 
93
#define _SYS_NSIG                       32
94
 
95
#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
96
#define _SYS_SIGMSG_MAXLEN      25
97
#else  /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
98
#define _SYS_SIGMSG_MAXLEN      0
99
#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
100
 
101
extern const char _string_syssigmsgs[];
102
 
103
 
104
#if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14
105
#define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14)
106
#else
107
#define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN
108
#endif
109
 
110
#if _SYS_SIGMSG_MAXLEN < __UIM_BUFLEN_INT + 15
111
#define _STRSIGNAL_BUFSIZE (__UIM_BUFLEN_INT + 15)
112
#else
113
#define _STRSIGNAL_BUFSIZE _SYS_SIGMSG_MAXLEN
114
#endif
115
 
116
/**********************************************************************/
117
#if defined(L__string_syserrmsgs) && defined(__UCLIBC_HAS_ERRNO_MESSAGES__)
118
 
119
const char _string_syserrmsgs[] = {
120
        /*   0:    0,  8 */ "Success\0"
121
        /*   1:    8, 24 */ "Operation not permitted\0"
122
        /*   2:   32, 26 */ "No such file or directory\0"
123
        /*   3:   58, 16 */ "No such process\0"
124
        /*   4:   74, 24 */ "Interrupted system call\0"
125
        /*   5:   98, 19 */ "Input/output error\0"
126
        /*   6:  117, 26 */ "No such device or address\0"
127
        /*   7:  143, 23 */ "Argument list too long\0"
128
        /*   8:  166, 18 */ "Exec format error\0"
129
        /*   9:  184, 20 */ "Bad file descriptor\0"
130
        /*  10:  204, 19 */ "No child processes\0"
131
        /*  11:  223, 33 */ "Resource temporarily unavailable\0"
132
        /*  12:  256, 23 */ "Cannot allocate memory\0"
133
        /*  13:  279, 18 */ "Permission denied\0"
134
        /*  14:  297, 12 */ "Bad address\0"
135
        /*  15:  309, 22 */ "Block device required\0"
136
        /*  16:  331, 24 */ "Device or resource busy\0"
137
        /*  17:  355, 12 */ "File exists\0"
138
        /*  18:  367, 26 */ "Invalid cross-device link\0"
139
        /*  19:  393, 15 */ "No such device\0"
140
        /*  20:  408, 16 */ "Not a directory\0"
141
        /*  21:  424, 15 */ "Is a directory\0"
142
        /*  22:  439, 17 */ "Invalid argument\0"
143
        /*  23:  456, 30 */ "Too many open files in system\0"
144
        /*  24:  486, 20 */ "Too many open files\0"
145
        /*  25:  506, 31 */ "Inappropriate ioctl for device\0"
146
        /*  26:  537, 15 */ "Text file busy\0"
147
        /*  27:  552, 15 */ "File too large\0"
148
        /*  28:  567, 24 */ "No space left on device\0"
149
        /*  29:  591, 13 */ "Illegal seek\0"
150
        /*  30:  604, 22 */ "Read-only file system\0"
151
        /*  31:  626, 15 */ "Too many links\0"
152
        /*  32:  641, 12 */ "Broken pipe\0"
153
        /*  33:  653, 33 */ "Numerical argument out of domain\0"
154
        /*  34:  686, 30 */ "Numerical result out of range\0"
155
        /*  35:  716, 26 */ "Resource deadlock avoided\0"
156
        /*  36:  742, 19 */ "File name too long\0"
157
        /*  37:  761, 19 */ "No locks available\0"
158
        /*  38:  780, 25 */ "Function not implemented\0"
159
        /*  39:  805, 20 */ "Directory not empty\0"
160
        /*  40:  825, 34 */ "Too many levels of symbolic links\0"
161
        /*  41:  859,  1 */ "\0"
162
        /*  42:  860, 27 */ "No message of desired type\0"
163
        /*  43:  887, 19 */ "Identifier removed\0"
164
        /*  44:  906, 28 */ "Channel number out of range\0"
165
        /*  45:  934, 25 */ "Level 2 not synchronized\0"
166
        /*  46:  959, 15 */ "Level 3 halted\0"
167
        /*  47:  974, 14 */ "Level 3 reset\0"
168
        /*  48:  988, 25 */ "Link number out of range\0"
169
        /*  49: 1013, 29 */ "Protocol driver not attached\0"
170
        /*  50: 1042, 27 */ "No CSI structure available\0"
171
        /*  51: 1069, 15 */ "Level 2 halted\0"
172
        /*  52: 1084, 17 */ "Invalid exchange\0"
173
        /*  53: 1101, 27 */ "Invalid request descriptor\0"
174
        /*  54: 1128, 14 */ "Exchange full\0"
175
        /*  55: 1142,  9 */ "No anode\0"
176
        /*  56: 1151, 21 */ "Invalid request code\0"
177
        /*  57: 1172, 13 */ "Invalid slot\0"
178
        /*  58: 1185,  1 */ "\0"
179
        /*  59: 1186, 21 */ "Bad font file format\0"
180
        /*  60: 1207, 20 */ "Device not a stream\0"
181
        /*  61: 1227, 18 */ "No data available\0"
182
        /*  62: 1245, 14 */ "Timer expired\0"
183
        /*  63: 1259, 25 */ "Out of streams resources\0"
184
        /*  64: 1284, 30 */ "Machine is not on the network\0"
185
        /*  65: 1314, 22 */ "Package not installed\0"
186
        /*  66: 1336, 17 */ "Object is remote\0"
187
        /*  67: 1353, 22 */ "Link has been severed\0"
188
        /*  68: 1375, 16 */ "Advertise error\0"
189
        /*  69: 1391, 14 */ "Srmount error\0"
190
        /*  70: 1405, 28 */ "Communication error on send\0"
191
        /*  71: 1433, 15 */ "Protocol error\0"
192
        /*  72: 1448, 19 */ "Multihop attempted\0"
193
        /*  73: 1467, 19 */ "RFS specific error\0"
194
        /*  74: 1486, 12 */ "Bad message\0"
195
        /*  75: 1498, 38 */ "Value too large for defined data type\0"
196
        /*  76: 1536, 27 */ "Name not unique on network\0"
197
        /*  77: 1563, 29 */ "File descriptor in bad state\0"
198
        /*  78: 1592, 23 */ "Remote address changed\0"
199
        /*  79: 1615, 39 */ "Can not access a needed shared library\0"
200
        /*  80: 1654, 37 */ "Accessing a corrupted shared library\0"
201
        /*  81: 1691, 32 */ ".lib section in a.out corrupted\0"
202
        /*  82: 1723, 48 */ "Attempting to link in too many shared libraries\0"
203
        /*  83: 1771, 38 */ "Cannot exec a shared library directly\0"
204
        /*  84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0"
205
        /*  85: 1859, 44 */ "Interrupted system call should be restarted\0"
206
        /*  86: 1903, 19 */ "Streams pipe error\0"
207
        /*  87: 1922, 15 */ "Too many users\0"
208
        /*  88: 1937, 31 */ "Socket operation on non-socket\0"
209
        /*  89: 1968, 29 */ "Destination address required\0"
210
        /*  90: 1997, 17 */ "Message too long\0"
211
        /*  91: 2014, 31 */ "Protocol wrong type for socket\0"
212
        /*  92: 2045, 23 */ "Protocol not available\0"
213
        /*  93: 2068, 23 */ "Protocol not supported\0"
214
        /*  94: 2091, 26 */ "Socket type not supported\0"
215
        /*  95: 2117, 24 */ "Operation not supported\0"
216
        /*  96: 2141, 30 */ "Protocol family not supported\0"
217
        /*  97: 2171, 41 */ "Address family not supported by protocol\0"
218
        /*  98: 2212, 23 */ "Address already in use\0"
219
        /*  99: 2235, 32 */ "Cannot assign requested address\0"
220
        /* 100: 2267, 16 */ "Network is down\0"
221
        /* 101: 2283, 23 */ "Network is unreachable\0"
222
        /* 102: 2306, 36 */ "Network dropped connection on reset\0"
223
        /* 103: 2342, 33 */ "Software caused connection abort\0"
224
        /* 104: 2375, 25 */ "Connection reset by peer\0"
225
        /* 105: 2400, 26 */ "No buffer space available\0"
226
        /* 106: 2426, 40 */ "Transport endpoint is already connected\0"
227
        /* 107: 2466, 36 */ "Transport endpoint is not connected\0"
228
        /* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0"
229
        /* 109: 2548, 35 */ "Too many references: cannot splice\0"
230
        /* 110: 2583, 21 */ "Connection timed out\0"
231
        /* 111: 2604, 19 */ "Connection refused\0"
232
        /* 112: 2623, 13 */ "Host is down\0"
233
        /* 113: 2636, 17 */ "No route to host\0"
234
        /* 114: 2653, 30 */ "Operation already in progress\0"
235
        /* 115: 2683, 26 */ "Operation now in progress\0"
236
        /* 116: 2709, 22 */ "Stale NFS file handle\0"
237
        /* 117: 2731, 25 */ "Structure needs cleaning\0"
238
        /* 118: 2756, 28 */ "Not a XENIX named type file\0"
239
        /* 119: 2784, 30 */ "No XENIX semaphores available\0"
240
        /* 120: 2814, 21 */ "Is a named type file\0"
241
        /* 121: 2835, 17 */ "Remote I/O error\0"
242
        /* 122: 2852, 20 */ "Disk quota exceeded\0"
243
        /* 123: 2872, 16 */ "No medium found\0"
244
        /* 124: 2888, 18 */ "Wrong medium type"
245
#if defined(__mips__) || defined(__sparc__)
246
        "\0"
247
        /* 125: 2906, 28 */ "File locking deadlock error"
248
#endif
249
        /* Note: for mips we are ignoring ECANCELED since glibc doesn't have a
250
         * corresponsding message.*/
251
};
252
 
253
#endif
254
/**********************************************************************/
255
#if defined(L_sys_errlist) && defined(__UCLIBC_HAS_SYS_ERRLIST__)
256
 
257
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.")
258
 
259
const char *const sys_errlist[] = {
260
        [0] =                            _string_syserrmsgs + 0,
261
        [EPERM] =                       _string_syserrmsgs + 8,
262
        [ENOENT] =                      _string_syserrmsgs + 32,
263
        [ESRCH] =                       _string_syserrmsgs + 58,
264
        [EINTR] =                       _string_syserrmsgs + 74,
265
        [EIO] =                         _string_syserrmsgs + 98,
266
        [ENXIO] =                       _string_syserrmsgs + 117,
267
        [E2BIG] =                       _string_syserrmsgs + 143,
268
        [ENOEXEC] =                     _string_syserrmsgs + 166,
269
        [EBADF] =                       _string_syserrmsgs + 184,
270
        [ECHILD] =                      _string_syserrmsgs + 204,
271
        [EAGAIN] =                      _string_syserrmsgs + 223,
272
        [ENOMEM] =                      _string_syserrmsgs + 256,
273
        [EACCES] =                      _string_syserrmsgs + 279,
274
        [EFAULT] =                      _string_syserrmsgs + 297,
275
        [ENOTBLK] =                     _string_syserrmsgs + 309,
276
        [EBUSY] =                       _string_syserrmsgs + 331,
277
        [EEXIST] =                      _string_syserrmsgs + 355,
278
        [EXDEV] =                       _string_syserrmsgs + 367,
279
        [ENODEV] =                      _string_syserrmsgs + 393,
280
        [ENOTDIR] =                     _string_syserrmsgs + 408,
281
        [EISDIR] =                      _string_syserrmsgs + 424,
282
        [EINVAL] =                      _string_syserrmsgs + 439,
283
        [ENFILE] =                      _string_syserrmsgs + 456,
284
        [EMFILE] =                      _string_syserrmsgs + 486,
285
        [ENOTTY] =                      _string_syserrmsgs + 506,
286
        [ETXTBSY] =                     _string_syserrmsgs + 537,
287
        [EFBIG] =                       _string_syserrmsgs + 552,
288
        [ENOSPC] =                      _string_syserrmsgs + 567,
289
        [ESPIPE] =                      _string_syserrmsgs + 591,
290
        [EROFS] =                       _string_syserrmsgs + 604,
291
        [EMLINK] =                      _string_syserrmsgs + 626,
292
        [EPIPE] =                       _string_syserrmsgs + 641,
293
        [EDOM] =                        _string_syserrmsgs + 653,
294
        [ERANGE] =                      _string_syserrmsgs + 686,
295
        [EDEADLK] =                     _string_syserrmsgs + 716,
296
        [ENAMETOOLONG] =        _string_syserrmsgs + 742,
297
        [ENOLCK] =                      _string_syserrmsgs + 761,
298
        [ENOSYS] =                      _string_syserrmsgs + 780,
299
        [ENOTEMPTY] =           _string_syserrmsgs + 805,
300
        [ELOOP] =                       _string_syserrmsgs + 825,
301
        /*      _string_syserrmsgs + 859, */
302
        [ENOMSG] =                      _string_syserrmsgs + 860,
303
        [EIDRM] =                       _string_syserrmsgs + 887,
304
        [ECHRNG] =                      _string_syserrmsgs + 906,
305
        [EL2NSYNC] =            _string_syserrmsgs + 934,
306
        [EL3HLT] =                      _string_syserrmsgs + 959,
307
        [EL3RST] =                      _string_syserrmsgs + 974,
308
        [ELNRNG] =                      _string_syserrmsgs + 988,
309
        [EUNATCH] =                     _string_syserrmsgs + 1013,
310
        [ENOCSI] =                      _string_syserrmsgs + 1042,
311
        [EL2HLT] =                      _string_syserrmsgs + 1069,
312
        [EBADE] =                       _string_syserrmsgs + 1084,
313
        [EBADR] =                       _string_syserrmsgs + 1101,
314
        [EXFULL] =                      _string_syserrmsgs + 1128,
315
        [ENOANO] =                      _string_syserrmsgs + 1142,
316
        [EBADRQC] =                     _string_syserrmsgs + 1151,
317
        [EBADSLT] =                     _string_syserrmsgs + 1172,
318
        /*      _string_syserrmsgs + 1185, */
319
        [EBFONT] =                      _string_syserrmsgs + 1186,
320
        [ENOSTR] =                      _string_syserrmsgs + 1207,
321
        [ENODATA] =                     _string_syserrmsgs + 1227,
322
        [ETIME] =                       _string_syserrmsgs + 1245,
323
        [ENOSR] =                       _string_syserrmsgs + 1259,
324
        [ENONET] =                      _string_syserrmsgs + 1284,
325
        [ENOPKG] =                      _string_syserrmsgs + 1314,
326
        [EREMOTE] =                     _string_syserrmsgs + 1336,
327
        [ENOLINK] =                     _string_syserrmsgs + 1353,
328
        [EADV] =                        _string_syserrmsgs + 1375,
329
        [ESRMNT] =                      _string_syserrmsgs + 1391,
330
        [ECOMM] =                       _string_syserrmsgs + 1405,
331
        [EPROTO] =                      _string_syserrmsgs + 1433,
332
        [EMULTIHOP] =           _string_syserrmsgs + 1448,
333
        [EDOTDOT] =                     _string_syserrmsgs + 1467,
334
        [EBADMSG] =                     _string_syserrmsgs + 1486,
335
        [EOVERFLOW] =           _string_syserrmsgs + 1498,
336
        [ENOTUNIQ] =            _string_syserrmsgs + 1536,
337
        [EBADFD] =                      _string_syserrmsgs + 1563,
338
        [EREMCHG] =                     _string_syserrmsgs + 1592,
339
        [ELIBACC] =                     _string_syserrmsgs + 1615,
340
        [ELIBBAD] =                     _string_syserrmsgs + 1654,
341
        [ELIBSCN] =                     _string_syserrmsgs + 1691,
342
        [ELIBMAX] =                     _string_syserrmsgs + 1723,
343
        [ELIBEXEC] =            _string_syserrmsgs + 1771,
344
        [EILSEQ] =                      _string_syserrmsgs + 1809,
345
        [ERESTART] =            _string_syserrmsgs + 1859,
346
        [ESTRPIPE] =            _string_syserrmsgs + 1903,
347
        [EUSERS] =                      _string_syserrmsgs + 1922,
348
        [ENOTSOCK] =            _string_syserrmsgs + 1937,
349
        [EDESTADDRREQ] =        _string_syserrmsgs + 1968,
350
        [EMSGSIZE] =            _string_syserrmsgs + 1997,
351
        [EPROTOTYPE] =          _string_syserrmsgs + 2014,
352
        [ENOPROTOOPT] =         _string_syserrmsgs + 2045,
353
        [EPROTONOSUPPORT] =     _string_syserrmsgs + 2068,
354
        [ESOCKTNOSUPPORT] =     _string_syserrmsgs + 2091,
355
        [EOPNOTSUPP] =          _string_syserrmsgs + 2117,
356
        [EPFNOSUPPORT] =        _string_syserrmsgs + 2141,
357
        [EAFNOSUPPORT] =        _string_syserrmsgs + 2171,
358
        [EADDRINUSE] =          _string_syserrmsgs + 2212,
359
        [EADDRNOTAVAIL] =       _string_syserrmsgs + 2235,
360
        [ENETDOWN] =            _string_syserrmsgs + 2267,
361
        [ENETUNREACH] =         _string_syserrmsgs + 2283,
362
        [ENETRESET] =           _string_syserrmsgs + 2306,
363
        [ECONNABORTED] =        _string_syserrmsgs + 2342,
364
        [ECONNRESET] =          _string_syserrmsgs + 2375,
365
        [ENOBUFS] =                     _string_syserrmsgs + 2400,
366
        [EISCONN] =                     _string_syserrmsgs + 2426,
367
        [ENOTCONN] =            _string_syserrmsgs + 2466,
368
        [ESHUTDOWN] =           _string_syserrmsgs + 2502,
369
        [ETOOMANYREFS] =        _string_syserrmsgs + 2548,
370
        [ETIMEDOUT] =           _string_syserrmsgs + 2583,
371
        [ECONNREFUSED] =        _string_syserrmsgs + 2604,
372
        [EHOSTDOWN] =           _string_syserrmsgs + 2623,
373
        [EHOSTUNREACH] =        _string_syserrmsgs + 2636,
374
        [EALREADY] =            _string_syserrmsgs + 2653,
375
        [EINPROGRESS] =         _string_syserrmsgs + 2683,
376
        [ESTALE] =                      _string_syserrmsgs + 2709,
377
        [EUCLEAN] =                     _string_syserrmsgs + 2731,
378
        [ENOTNAM] =                     _string_syserrmsgs + 2756,
379
        [ENAVAIL] =                     _string_syserrmsgs + 2784,
380
        [EISNAM] =                      _string_syserrmsgs + 2814,
381
        [EREMOTEIO] =           _string_syserrmsgs + 2835,
382
        [EDQUOT] =                      _string_syserrmsgs + 2852,
383
        [ENOMEDIUM] =           _string_syserrmsgs + 2872,
384
        [EMEDIUMTYPE] =         _string_syserrmsgs + 2888,
385
 
386
#if EDEADLOCK != EDEADLK
387
        [EDEADLOCK] =           _string_syserrmsgs + 2906,
388
#endif
389
 
390
#if EWOULDBLOCK != EAGAIN
391
#error EWOULDBLOCK does not equal EAGAIN
392
#endif
393
 
394
        /* For now, ignore the other arch-specific errors.  glibc only maps EPROCLIM. */
395
 
396
        /* some other mips errors */
397
#ifdef ECANCELED
398
#endif
399
#ifdef EINIT
400
#endif
401
#ifdef EREMDEV
402
#endif
403
 
404
        /* some other sparc errors */
405
#ifdef EPROCLIM
406
#endif
407
#ifdef ERREMOTE
408
#endif
409
};
410
 
411
int sys_nerr = sizeof(sys_errlist)/sizeof(sys_errlist[0]);
412
 
413
#endif
414
/**********************************************************************/
415
#ifdef L_wmemcpy
416
#define L_memcpy
417
#define Wmemcpy wmemcpy
418
#else
419
#define Wmemcpy memcpy
420
#endif
421
 
422
#ifdef L_memcpy
423
 
424
Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
425
{
426
        register Wchar *r1 = s1;
427
        register const Wchar *r2 = s2;
428
 
429
#ifdef __BCC__
430
        while (n--) {
431
                *r1++ = *r2++;
432
        }
433
#else
434
        while (n) {
435
                *r1++ = *r2++;
436
                --n;
437
        }
438
#endif
439
 
440
        return s1;
441
}
442
 
443
#endif
444
/**********************************************************************/
445
#ifdef L_wmemmove
446
#define L_memmove
447
#define Wmemmove wmemmove
448
#else
449
#define Wmemmove memmove
450
#endif
451
 
452
#ifdef L_memmove
453
 
454
Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n)
455
{
456
#ifdef __BCC__
457
        register Wchar *s = (Wchar *) s1;
458
        register const Wchar *p = (const Wchar *) s2;
459
 
460
        if (p >= s) {
461
                while (n--) {
462
                        *s++ = *p++;
463
                }
464
        } else {
465
                s += n;
466
                p += n;
467
                while (n--) {
468
                        *--s = *--p;
469
                }
470
        }
471
 
472
        return s1;
473
#else
474
        register Wchar *s = (Wchar *) s1;
475
        register const Wchar *p = (const Wchar *) s2;
476
 
477
        if (p >= s) {
478
                while (n) {
479
                        *s++ = *p++;
480
                        --n;
481
                }
482
        } else {
483
                while (n) {
484
                        --n;
485
                        s[n] = p[n];
486
                }
487
        }
488
 
489
        return s1;
490
#endif
491
}
492
 
493
#endif
494
/**********************************************************************/
495
#ifdef L_wcscpy
496
#define L_strcpy
497
#define Wstrcpy wcscpy
498
#else
499
#define Wstrcpy strcpy
500
#endif
501
 
502
#ifdef L_strcpy
503
 
504
Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2)
505
{
506
        register Wchar *s = s1;
507
 
508
#ifdef __BCC__
509
        do {
510
                *s = *s2++;
511
        } while (*s++ != 0);
512
#else
513
        while ( (*s++ = *s2++) != 0 );
514
#endif
515
 
516
        return s1;
517
}
518
 
519
#endif
520
/**********************************************************************/
521
#ifdef L_wcsncpy
522
#define L_strncpy
523
#define Wstrncpy wcsncpy
524
#else
525
#define Wstrncpy strncpy
526
#endif
527
 
528
#ifdef L_strncpy
529
 
530
Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2,
531
                                size_t n)
532
{
533
        register Wchar *s = s1;
534
 
535
#ifdef __BCC__
536
        while (n--) {
537
                if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
538
                ++s;
539
        }
540
#else
541
        while (n) {
542
                if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
543
                ++s;
544
                --n;
545
        }
546
#endif
547
 
548
        return s1;
549
}
550
 
551
#endif
552
/**********************************************************************/
553
#ifdef L_wcscat
554
#define L_strcat
555
#define Wstrcat wcscat
556
#else
557
#define Wstrcat strcat
558
#endif
559
 
560
#ifdef L_strcat
561
 
562
Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2)
563
{
564
        register Wchar *s = s1;
565
 
566
        while (*s++);
567
        --s;
568
        while ((*s++ = *s2++) != 0);
569
 
570
        return s1;
571
}
572
 
573
#endif
574
/**********************************************************************/
575
#ifdef L_wcsncat
576
#define L_strncat
577
#define Wstrncat wcsncat
578
#else
579
#define Wstrncat strncat
580
#endif
581
 
582
#ifdef L_strncat
583
 
584
Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2,
585
                                size_t n)
586
{
587
        register Wchar *s = s1;
588
 
589
        while (*s++);
590
        --s;
591
#if __BCC__
592
        while (n-- && ((*s = *s2++) != 0)) ++s;
593
#else
594
        while (n && ((*s = *s2++) != 0)) {
595
                --n;
596
                ++s;
597
        }
598
#endif
599
        *s = 0;
600
 
601
        return s1;
602
}
603
 
604
#endif
605
/**********************************************************************/
606
#ifdef L_wmemcmp
607
#define L_memcmp
608
#define Wmemcmp wmemcmp
609
#else
610
#define Wmemcmp memcmp
611
#endif
612
 
613
#ifdef L_memcmp
614
 
615
#ifndef L_wmemcmp
616
weak_alias(memcmp,bcmp);
617
#endif
618
 
619
int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
620
{
621
        register const Wuchar *r1 = (const Wuchar *) s1;
622
        register const Wuchar *r2 = (const Wuchar *) s2;
623
 
624
#ifdef WANT_WIDE
625
        while (n && (*r1 == *r2)) {
626
                ++r1;
627
                ++r2;
628
                --n;
629
        }
630
 
631
        return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1);
632
#else
633
        int r = 0;
634
 
635
        while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0));
636
 
637
        return r;
638
#endif
639
}
640
 
641
#endif
642
/**********************************************************************/
643
#ifdef L_wcscmp
644
#define L_strcmp
645
#define Wstrcmp wcscmp
646
#else
647
#define Wstrcmp strcmp
648
#endif
649
 
650
#ifdef L_strcmp
651
 
652
#ifdef __LOCALE_C_ONLY
653
#ifdef L_wcscmp
654
weak_alias(wcscmp,wcscoll);
655
#else  /* L_wcscmp */
656
weak_alias(strcmp,strcoll);
657
#endif /* L_wcscmp */
658
#endif /* __LOCALE_C_ONLY */
659
 
660
int Wstrcmp(register const Wchar *s1, register const Wchar *s2)
661
{
662
#ifdef WANT_WIDE
663
        while (*((Wuchar *)s1) == *((Wuchar *)s2)) {
664
                if (!*s1++) {
665
                        return 0;
666
                }
667
                ++s2;
668
        }
669
 
670
        return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1;
671
#else
672
        int r;
673
 
674
        while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++))
675
                        == 0) && *s1++);
676
 
677
        return r;
678
#endif
679
}
680
#endif
681
/**********************************************************************/
682
#ifdef L_wcsncmp
683
#define L_strncmp
684
#define Wstrncmp wcsncmp
685
#else
686
#define Wstrncmp strncmp
687
#endif
688
 
689
#ifdef L_strncmp
690
 
691
int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n)
692
{
693
#ifdef WANT_WIDE
694
        while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) {
695
                if (!*s1++) {
696
                        return 0;
697
                }
698
                ++s2;
699
                --n;
700
        }
701
 
702
        return (n == 0) ? 0 : ((*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1);
703
#else
704
        int r = 0;
705
 
706
        while (n--
707
                   && ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++))
708
                        == 0)
709
                   && *s1++);
710
 
711
        return r;
712
#endif
713
}
714
 
715
#endif
716
/**********************************************************************/
717
#ifdef L_wmemchr
718
#define L_memchr
719
#define Wmemchr wmemchr
720
#else
721
#define Wmemchr memchr
722
#endif
723
 
724
#ifdef L_memchr
725
 
726
Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n)
727
{
728
        register const Wuchar *r = (const Wuchar *) s;
729
#ifdef __BCC__
730
        /* bcc can optimize the counter if it thinks it is a pointer... */
731
        register const char *np = (const char *) n;
732
#else
733
#define np n
734
#endif
735
 
736
        while (np) {
737
                if (*r == ((Wuchar)c)) {
738
                        return (Wvoid *) r;     /* silence the warning */
739
                }
740
                ++r;
741
                --np;
742
        }
743
 
744
        return NULL;
745
}
746
#undef np
747
 
748
#endif
749
/**********************************************************************/
750
#ifdef L_wcschr
751
#define L_strchr
752
#define Wstrchr wcschr
753
#else
754
#define Wstrchr strchr
755
#endif
756
 
757
#ifdef L_strchr
758
 
759
#ifndef L_wcschr
760
weak_alias(strchr,index);
761
#endif
762
 
763
Wchar *Wstrchr(register const Wchar *s, Wint c)
764
{
765
        do {
766
                if (*s == ((Wchar)c)) {
767
                        return (Wchar *) s;     /* silence the warning */
768
                }
769
        } while (*s++);
770
 
771
        return NULL;
772
}
773
 
774
#endif
775
/**********************************************************************/
776
#ifdef L_wcscspn
777
#define L_strcspn
778
#define Wstrcspn wcscspn
779
#else
780
#define Wstrcspn strcspn
781
#endif
782
 
783
#ifdef L_strcspn
784
 
785
size_t Wstrcspn(const Wchar *s1, const Wchar *s2)
786
{
787
        register const Wchar *s;
788
        register const Wchar *p;
789
 
790
        for ( s=s1 ; *s ; s++ ) {
791
                for ( p=s2 ; *p ; p++ ) {
792
                        if (*p == *s) goto done;
793
                }
794
        }
795
 done:
796
        return s - s1;
797
}
798
 
799
#endif
800
/**********************************************************************/
801
#ifdef L_wcspbrk
802
#define L_strpbrk
803
#define Wstrpbrk wcspbrk
804
#else
805
#define Wstrpbrk strpbrk
806
#endif
807
 
808
#ifdef L_strpbrk
809
 
810
Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2)
811
{
812
        register const Wchar *s;
813
        register const Wchar *p;
814
 
815
        for ( s=s1 ; *s ; s++ ) {
816
                for ( p=s2 ; *p ; p++ ) {
817
                        if (*p == *s) return (Wchar *) s; /* silence the warning */
818
                }
819
        }
820
        return NULL;
821
}
822
#endif
823
/**********************************************************************/
824
#ifdef L_wcsrchr
825
#define L_strrchr
826
#define Wstrrchr wcsrchr
827
#else
828
#define Wstrrchr strrchr
829
#endif
830
 
831
#ifdef L_strrchr
832
 
833
#ifndef L_wcsrchr
834
weak_alias(strrchr,rindex);
835
#endif
836
 
837
Wchar *Wstrrchr(register const  Wchar *s, Wint c)
838
{
839
        register const Wchar *p;
840
 
841
        p = NULL;
842
        do {
843
                if (*s == (Wchar) c) {
844
                        p = s;
845
                }
846
        } while (*s++);
847
 
848
        return (Wchar *) p;                     /* silence the warning */
849
}
850
 
851
#endif
852
/**********************************************************************/
853
#ifdef L_wcsspn
854
#define L_strspn
855
#define Wstrspn wcsspn
856
#else
857
#define Wstrspn strspn
858
#endif
859
 
860
#ifdef L_strspn
861
 
862
size_t Wstrspn(const Wchar *s1, const Wchar *s2)
863
{
864
        register const Wchar *s = s1;
865
        register const Wchar *p = s2;
866
 
867
        while (*p) {
868
                if (*p++ == *s) {
869
                        ++s;
870
                        p = s2;
871
                }
872
        }
873
        return s - s1;
874
}
875
 
876
#endif
877
/**********************************************************************/
878
#ifdef L_wcsstr
879
#define L_strstr
880
#define Wstrstr wcsstr
881
#else
882
#define Wstrstr strstr
883
#endif
884
 
885
#ifdef L_strstr
886
 
887
/* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */
888
 
889
#ifdef L_wcsstr
890
weak_alias(wcsstr,wcswcs);
891
#endif
892
 
893
Wchar *Wstrstr(const Wchar *s1, const Wchar *s2)
894
{
895
        register const Wchar *s = s1;
896
        register const Wchar *p = s2;
897
 
898
        do {
899
                if (!*p) {
900
                        return (Wchar *) s1;;
901
                }
902
                if (*p == *s) {
903
                        ++p;
904
                        ++s;
905
                } else {
906
                        p = s2;
907
                        if (!*s) {
908
                                return NULL;
909
                        }
910
                        s = ++s1;
911
                }
912
        } while (1);
913
}
914
 
915
#endif
916
/**********************************************************************/
917
#undef Wstrspn
918
#undef Wstrpbrk
919
 
920
#ifdef L_wcstok
921
#define L_strtok_r
922
#define Wstrtok_r wcstok
923
#define Wstrspn wcsspn
924
#define Wstrpbrk wcspbrk
925
#else
926
#define Wstrtok_r strtok_r
927
#define Wstrspn strspn
928
#define Wstrpbrk strpbrk
929
#endif
930
 
931
#ifdef L_strtok_r
932
 
933
Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2,
934
                                 Wchar ** __restrict next_start)
935
{
936
        register Wchar *s;
937
        register Wchar *p;
938
 
939
#if 1
940
        if (((s = s1) != NULL) || ((s = *next_start) != NULL)) {
941
                if (*(s += Wstrspn(s, s2))) {
942
                        if ((p = Wstrpbrk(s, s2)) != NULL) {
943
                                *p++ = 0;
944
                        }
945
                } else {
946
                        p = s = NULL;
947
                }
948
                *next_start = p;
949
        }
950
        return s;
951
#else
952
        if (!(s = s1)) {
953
                s = *next_start;
954
        }
955
        if (s && *(s += Wstrspn(s, s2))) {
956
                if (*(p = s + Wstrcspn(s, s2))) {
957
                        *p++ = 0;
958
                }
959
                *next_start = p;
960
                return s;
961
        }
962
        return NULL;                            /* TODO: set *next_start = NULL for safety? */
963
#endif
964
}
965
 
966
#endif
967
/**********************************************************************/
968
/*  #ifdef L_wcstok */
969
/*  #define L_strtok */
970
/*  #define Wstrtok wcstok */
971
/*  #define Wstrtok_r wcstok_r */
972
/*  #else */
973
/*  #define Wstrtok strtok */
974
/*  #define Wstrtok_r strtok_r */
975
/*  #endif */
976
 
977
#ifdef L_strtok
978
#define Wstrtok strtok
979
#define Wstrtok_r strtok_r
980
 
981
Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2)
982
{
983
        static Wchar *next_start;       /* Initialized to 0 since in bss. */
984
        return Wstrtok_r(s1, s2, &next_start);
985
}
986
 
987
#endif
988
/**********************************************************************/
989
#ifdef L_wmemset
990
#define L_memset
991
#define Wmemset wmemset
992
#else
993
#define Wmemset memset
994
#endif
995
 
996
#ifdef L_memset
997
 
998
Wvoid *Wmemset(Wvoid *s, Wint c, size_t n)
999
{
1000
        register Wuchar *p = (Wuchar *) s;
1001
#ifdef __BCC__
1002
        /* bcc can optimize the counter if it thinks it is a pointer... */
1003
        register const char *np = (const char *) n;
1004
#else
1005
#define np n
1006
#endif
1007
 
1008
        while (np) {
1009
                *p++ = (Wuchar) c;
1010
                --np;
1011
        }
1012
 
1013
        return s;
1014
}
1015
#undef np
1016
 
1017
#endif
1018
/**********************************************************************/
1019
#ifdef L_wcslen
1020
#define L_strlen
1021
#define Wstrlen wcslen
1022
#else
1023
#define Wstrlen strlen
1024
#endif
1025
 
1026
#ifdef L_strlen
1027
 
1028
size_t Wstrlen(const Wchar *s)
1029
{
1030
        register const Wchar *p;
1031
 
1032
        for (p=s ; *p ; p++);
1033
 
1034
        return p - s;
1035
}
1036
 
1037
#endif
1038
/**********************************************************************/
1039
/* ANSI/ISO end here */
1040
/**********************************************************************/
1041
#ifdef L_ffs
1042
 
1043
int ffs(int i)
1044
{
1045
#if 1
1046
        /* inlined binary search method */
1047
        char n = 1;
1048
#if UINT_MAX == 0xffffU
1049
        /* nothing to do here -- just trying to avoiding possible problems */
1050
#elif UINT_MAX == 0xffffffffU
1051
        if (!(i & 0xffff)) {
1052
                n += 16;
1053
                i >>= 16;
1054
        }
1055
#else
1056
#error ffs needs rewriting!
1057
#endif
1058
 
1059
        if (!(i & 0xff)) {
1060
                n += 8;
1061
                i >>= 8;
1062
        }
1063
        if (!(i & 0x0f)) {
1064
                n += 4;
1065
                i >>= 4;
1066
        }
1067
        if (!(i & 0x03)) {
1068
                n += 2;
1069
                i >>= 2;
1070
        }
1071
        return (i) ? (n + ((i+1) & 0x01)) : 0;
1072
 
1073
#else
1074
        /* linear search -- slow, but small */
1075
        int n;
1076
 
1077
        for (n = 0 ; i ; ++n) {
1078
                i >>= 1;
1079
        }
1080
 
1081
        return n;
1082
#endif
1083
}
1084
 
1085
#endif
1086
/**********************************************************************/
1087
#if defined(L_strcasecmp) || defined(L_strcasecmp_l) || defined(L_wcscasecmp) || defined(L_wcscasecmp_l)
1088
 
1089
#if defined(L_wcscasecmp) || defined(L_wcscasecmp_l)
1090
 
1091
#define strcasecmp wcscasecmp
1092
#define strcasecmp_l wcscasecmp_l
1093
#define __strcasecmp_l __wcscasecmp_l
1094
#ifdef __UCLIBC_DO_XLOCALE
1095
#define TOLOWER(C) __towlower_l((C), locale_arg)
1096
#else
1097
#define TOLOWER(C) towlower((C))
1098
#endif
1099
 
1100
#else  /* defined(L_wcscasecmp) || defined(L_wcscasecmp_l) */
1101
 
1102
#ifdef __UCLIBC_DO_XLOCALE
1103
#define TOLOWER(C) __tolower_l((C), locale_arg)
1104
#else
1105
#define TOLOWER(C) tolower((C))
1106
#endif
1107
 
1108
#endif /* defined(L_wcscasecmp) || defined(L_wcscasecmp_l) */
1109
 
1110
 
1111
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
1112
 
1113
int strcasecmp(register const Wchar *s1, register const Wchar *s2)
1114
{
1115
        return __strcasecmp_l(s1, s2, __UCLIBC_CURLOCALE);
1116
}
1117
 
1118
#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
1119
 
1120
int __XL(strcasecmp)(register const Wchar *s1, register const Wchar *s2
1121
                                          __LOCALE_PARAM )
1122
{
1123
#ifdef WANT_WIDE
1124
        while ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2))) {
1125
                if (!*s1++) {
1126
                        return 0;
1127
                }
1128
                ++s2;
1129
        }
1130
 
1131
        return (((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1;
1132
        /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
1133
#else
1134
        int r = 0;
1135
 
1136
        while ( ((s1 == s2) ||
1137
                         !(r = ((int)( TOLOWER(*((Wuchar *)s1))))
1138
                           - TOLOWER(*((Wuchar *)s2))))
1139
                        && (++s2, *s1++));
1140
 
1141
        return r;
1142
#endif
1143
}
1144
 
1145
__XL_ALIAS(strcasecmp)
1146
 
1147
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
1148
 
1149
#endif
1150
/**********************************************************************/
1151
#if defined(L_strncasecmp) || defined(L_strncasecmp_l) || defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l)
1152
 
1153
#if defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l)
1154
 
1155
#define strncasecmp wcsncasecmp
1156
#define strncasecmp_l wcsncasecmp_l
1157
#define __strncasecmp_l __wcsncasecmp_l
1158
#ifdef __UCLIBC_DO_XLOCALE
1159
#define TOLOWER(C) __towlower_l((C), locale_arg)
1160
#else
1161
#define TOLOWER(C) towlower((C))
1162
#endif
1163
 
1164
#else  /* defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l) */
1165
 
1166
#ifdef __UCLIBC_DO_XLOCALE
1167
#define TOLOWER(C) __tolower_l((C), locale_arg)
1168
#else
1169
#define TOLOWER(C) tolower((C))
1170
#endif
1171
 
1172
#endif /* defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l) */
1173
 
1174
 
1175
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
1176
 
1177
int strncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n)
1178
{
1179
        return __strncasecmp_l(s1, s2, n, __UCLIBC_CURLOCALE);
1180
}
1181
 
1182
#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
1183
 
1184
int __XL(strncasecmp)(register const Wchar *s1, register const Wchar *s2,
1185
                                          size_t n   __LOCALE_PARAM )
1186
{
1187
#ifdef WANT_WIDE
1188
        while (n && ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2)))) {
1189
                if (!*s1++) {
1190
                        return 0;
1191
                }
1192
                ++s2;
1193
                --n;
1194
        }
1195
 
1196
        return (n == 0)
1197
                ? 0
1198
                : ((((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1);
1199
        /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
1200
#else
1201
        int r = 0;
1202
 
1203
        while ( n
1204
                        && ((s1 == s2) ||
1205
                                !(r = ((int)( TOLOWER(*((unsigned char *)s1))))
1206
                                  - TOLOWER(*((unsigned char *)s2))))
1207
                        && (--n, ++s2, *s1++));
1208
        return r;
1209
#endif
1210
}
1211
 
1212
__XL_ALIAS(strncasecmp)
1213
 
1214
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
1215
 
1216
#endif
1217
/**********************************************************************/
1218
#ifdef L_wcsnlen
1219
#define L_strnlen
1220
#define Wstrnlen wcsnlen
1221
#else
1222
#define Wstrnlen strnlen
1223
#endif
1224
 
1225
#ifdef L_strnlen
1226
 
1227
size_t Wstrnlen(const Wchar *s, size_t max)
1228
{
1229
        register const Wchar *p = s;
1230
#ifdef __BCC__
1231
        /* bcc can optimize the counter if it thinks it is a pointer... */
1232
        register const char *maxp = (const char *) max;
1233
#else
1234
#define maxp max
1235
#endif
1236
 
1237
        while (maxp && *p) {
1238
                ++p;
1239
                --maxp;
1240
        }
1241
 
1242
        return p - s;
1243
}
1244
#undef maxp
1245
#endif
1246
/**********************************************************************/
1247
/* No wide analog. */
1248
 
1249
#ifdef L_memccpy
1250
 
1251
void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n)
1252
{
1253
        register char *r1 = s1;
1254
        register const char *r2 = s2;
1255
 
1256
        while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c)));
1257
 
1258
        return (n == (size_t) -1) ? NULL : r1;
1259
}
1260
 
1261
#endif
1262
/**********************************************************************/
1263
#undef Wstrlen
1264
#undef Wstrcpy
1265
 
1266
#ifdef L_wcsdup
1267
#define L_strdup
1268
#define Wstrdup wcsdup
1269
#define Wstrlen wcslen
1270
#define Wstrcpy wcscpy
1271
#else
1272
#define Wstrdup strdup
1273
#define Wstrlen strlen
1274
#define Wstrcpy strcpy
1275
#endif
1276
 
1277
#ifdef L_strdup
1278
 
1279
Wchar *Wstrdup(register const Wchar *s1)
1280
{
1281
        register Wchar *s;
1282
 
1283
    if ((s = malloc((Wstrlen(s1) + 1) * sizeof(Wchar))) != NULL) {
1284
                Wstrcpy(s, s1);
1285
        }
1286
 
1287
        return s;
1288
}
1289
 
1290
#endif
1291
/**********************************************************************/
1292
#ifdef L_strerror
1293
 
1294
char *strerror(int errnum)
1295
{
1296
    static char buf[_STRERROR_BUFSIZE];
1297
 
1298
        _susv3_strerror_r(errnum, buf, sizeof(buf));
1299
 
1300
        return buf;
1301
}
1302
 
1303
#endif
1304
/**********************************************************************/
1305
/* SUSv3 functions. */
1306
/**********************************************************************/
1307
#ifdef L__susv3_strerror_r
1308
 
1309
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
1310
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
1311
 
1312
static const unsigned char estridx[] = {
1313
        0,                                                       /* success is always 0 */
1314
        EPERM,
1315
        ENOENT,
1316
        ESRCH,
1317
        EINTR,
1318
        EIO,
1319
        ENXIO,
1320
        E2BIG,
1321
        ENOEXEC,
1322
        EBADF,
1323
        ECHILD,
1324
        EAGAIN,
1325
        ENOMEM,
1326
        EACCES,
1327
        EFAULT,
1328
        ENOTBLK,
1329
        EBUSY,
1330
        EEXIST,
1331
        EXDEV,
1332
        ENODEV,
1333
        ENOTDIR,
1334
        EISDIR,
1335
        EINVAL,
1336
        ENFILE,
1337
        EMFILE,
1338
        ENOTTY,
1339
        ETXTBSY,
1340
        EFBIG,
1341
        ENOSPC,
1342
        ESPIPE,
1343
        EROFS,
1344
        EMLINK,
1345
        EPIPE,
1346
        EDOM,
1347
        ERANGE,
1348
        EDEADLK,
1349
        ENAMETOOLONG,
1350
        ENOLCK,
1351
        ENOSYS,
1352
        ENOTEMPTY,
1353
        ELOOP,
1354
        0,
1355
        ENOMSG,
1356
        EIDRM,
1357
        ECHRNG,
1358
        EL2NSYNC,
1359
        EL3HLT,
1360
        EL3RST,
1361
        ELNRNG,
1362
        EUNATCH,
1363
        ENOCSI,
1364
        EL2HLT,
1365
        EBADE,
1366
        EBADR,
1367
        EXFULL,
1368
        ENOANO,
1369
        EBADRQC,
1370
        EBADSLT,
1371
        0,
1372
        EBFONT,
1373
        ENOSTR,
1374
        ENODATA,
1375
        ETIME,
1376
        ENOSR,
1377
        ENONET,
1378
        ENOPKG,
1379
        EREMOTE,
1380
        ENOLINK,
1381
        EADV,
1382
        ESRMNT,
1383
        ECOMM,
1384
        EPROTO,
1385
        EMULTIHOP,
1386
        EDOTDOT,
1387
        EBADMSG,
1388
        EOVERFLOW,
1389
        ENOTUNIQ,
1390
        EBADFD,
1391
        EREMCHG,
1392
        ELIBACC,
1393
        ELIBBAD,
1394
        ELIBSCN,
1395
        ELIBMAX,
1396
        ELIBEXEC,
1397
        EILSEQ,
1398
        ERESTART,
1399
        ESTRPIPE,
1400
        EUSERS,
1401
        ENOTSOCK,
1402
        EDESTADDRREQ,
1403
        EMSGSIZE,
1404
        EPROTOTYPE,
1405
        ENOPROTOOPT,
1406
        EPROTONOSUPPORT,
1407
        ESOCKTNOSUPPORT,
1408
        EOPNOTSUPP,
1409
        EPFNOSUPPORT,
1410
        EAFNOSUPPORT,
1411
        EADDRINUSE,
1412
        EADDRNOTAVAIL,
1413
        ENETDOWN,
1414
        ENETUNREACH,
1415
        ENETRESET,
1416
        ECONNABORTED,
1417
        ECONNRESET,
1418
        ENOBUFS,
1419
        EISCONN,
1420
        ENOTCONN,
1421
        ESHUTDOWN,
1422
        ETOOMANYREFS,
1423
        ETIMEDOUT,
1424
        ECONNREFUSED,
1425
        EHOSTDOWN,
1426
        EHOSTUNREACH,
1427
        EALREADY,
1428
        EINPROGRESS,
1429
        ESTALE,
1430
        EUCLEAN,
1431
        ENOTNAM,
1432
        ENAVAIL,
1433
        EISNAM,
1434
        EREMOTEIO,
1435
#ifdef __mips__
1436
        0,                                                       /* mips has an outrageous value for this... */
1437
#else
1438
        EDQUOT,
1439
#endif
1440
        ENOMEDIUM,
1441
        EMEDIUMTYPE,
1442
#if defined(__mips__) || defined(__sparc__)
1443
        EDEADLOCK,
1444
#endif
1445
};
1446
 
1447
#endif
1448
 
1449
int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
1450
{
1451
    register char *s;
1452
    int i, retval;
1453
    char buf[_STRERROR_BUFSIZE];
1454
    static const char unknown[] = {
1455
                'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
1456
    };
1457
 
1458
    retval = EINVAL;
1459
 
1460
 
1461
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
1462
 
1463
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
1464
        /* Need to translate errno to string index. */
1465
        for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) {
1466
                if (estridx[i] == errnum) {
1467
                        goto GOT_ESTRIDX;
1468
                }
1469
        }
1470
        i = INT_MAX;    /* Failed, but may need to check mips special case. */
1471
#ifdef __mips__
1472
        if (errnum == EDQUOT) { /* Deal with large EDQUOT value on mips */
1473
                i = 122;
1474
        }
1475
#endif /* __mips__ */
1476
 GOT_ESTRIDX:
1477
#else
1478
        /* No errno to string index translation needed. */
1479
        i = errnum;
1480
#endif
1481
 
1482
    if (((unsigned int) i) < _SYS_NERR) {
1483
                /* Trade time for space.  This function should rarely be called
1484
                 * so rather than keeping an array of pointers for the different
1485
                 * messages, just run through the buffer until we find the
1486
                 * correct string. */
1487
                for (s = (char *) _string_syserrmsgs ; i ; ++s) {
1488
                        if (!*s) {
1489
                                --i;
1490
                        }
1491
                }
1492
                if (*s) {               /* Make sure we have an actual message. */
1493
                        retval = 0;
1494
                        goto GOT_MESG;
1495
                }
1496
    }
1497
 
1498
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
1499
 
1500
    s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
1501
    memcpy(s, unknown, sizeof(unknown));
1502
 
1503
 GOT_MESG:
1504
    if (!strerrbuf) {           /* SUSv3  */
1505
                buflen = 0;
1506
    }
1507
    i = strlen(s) + 1;
1508
    if (i > buflen) {
1509
                i = buflen;
1510
                retval = ERANGE;
1511
    }
1512
 
1513
    if (i) {
1514
                memcpy(strerrbuf, s, i);
1515
                strerrbuf[i-1] = 0;      /* In case buf was too small. */
1516
    }
1517
 
1518
    if (retval) {
1519
                __set_errno(retval);
1520
    }
1521
 
1522
    return retval;
1523
}
1524
 
1525
#else  /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
1526
 
1527
int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
1528
{
1529
    register char *s;
1530
    int i, retval;
1531
    char buf[_STRERROR_BUFSIZE];
1532
    static const char unknown[] = {
1533
                'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
1534
    };
1535
 
1536
    s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
1537
    memcpy(s, unknown, sizeof(unknown));
1538
 
1539
    if (!strerrbuf) {           /* SUSv3  */
1540
                buflen = 0;
1541
    }
1542
 
1543
    retval = EINVAL;
1544
 
1545
        i = buf + sizeof(buf) - s;
1546
 
1547
    if (i > buflen) {
1548
                i = buflen;
1549
                retval = ERANGE;
1550
    }
1551
 
1552
    if (i) {
1553
                memcpy(strerrbuf, s, i);
1554
                strerrbuf[i-1] = 0;      /* In case buf was too small. */
1555
    }
1556
 
1557
        __set_errno(retval);
1558
 
1559
    return retval;
1560
}
1561
 
1562
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
1563
 
1564
#endif
1565
/**********************************************************************/
1566
/* GNU extension functions. */
1567
/**********************************************************************/
1568
#ifdef L__glibc_strerror_r
1569
 
1570
weak_alias(_glibc_strerror_r,__strerror_r);
1571
 
1572
char *_glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen)
1573
{
1574
    _susv3_strerror_r(errnum, strerrbuf, buflen);
1575
 
1576
    return strerrbuf;
1577
}
1578
 
1579
#endif
1580
/**********************************************************************/
1581
#ifdef L_memmem
1582
 
1583
void *memmem(const void *haystack, size_t haystacklen,
1584
                     const void *needle, size_t needlelen)
1585
{
1586
        register const char *ph;
1587
        register const char *pn;
1588
        const char *plast;
1589
        size_t n;
1590
 
1591
        if (needlelen == 0) {
1592
                return (void *) haystack;
1593
        }
1594
 
1595
        if (haystacklen >= needlelen) {
1596
                ph = (const char *) haystack;
1597
                pn = (const char *) needle;
1598
                plast = ph + (haystacklen - needlelen);
1599
 
1600
                do {
1601
                        n = 0;
1602
                        while (ph[n] == pn[n]) {
1603
                                if (++n == needlelen) {
1604
                                        return (void *) ph;
1605
                                }
1606
                        }
1607
                } while (++ph <= plast);
1608
        }
1609
 
1610
        return NULL;
1611
}
1612
 
1613
#endif
1614
/**********************************************************************/
1615
#ifdef L_wmempcpy
1616
#define L_mempcpy
1617
#define Wmempcpy wmempcpy
1618
#else
1619
#define Wmempcpy mempcpy
1620
#endif
1621
 
1622
#ifdef L_mempcpy
1623
 
1624
#ifndef L_wmempcpy
1625
/* uClibc's old string implementation did this to cater to some app. */
1626
weak_alias(mempcpy,__mempcpy);
1627
#endif
1628
 
1629
Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
1630
{
1631
        register Wchar *r1 = s1;
1632
        register const Wchar *r2 = s2;
1633
 
1634
#ifdef __BCC__
1635
        while (n--) {
1636
                *r1++ = *r2++;
1637
        }
1638
#else
1639
        while (n) {
1640
                *r1++ = *r2++;
1641
                --n;
1642
        }
1643
#endif
1644
 
1645
        return r1;
1646
}
1647
 
1648
#endif
1649
/**********************************************************************/
1650
#ifdef L_memrchr
1651
 
1652
void *memrchr(const void *s, int c, size_t n)
1653
{
1654
        register const unsigned char *r;
1655
#ifdef __BCC__
1656
        /* bcc can optimize the counter if it thinks it is a pointer... */
1657
        register const char *np = (const char *) n;
1658
#else
1659
#define np n
1660
#endif
1661
 
1662
        r = ((unsigned char *)s) + ((size_t) np);
1663
 
1664
        while (np) {
1665
                if (*--r == ((unsigned char)c)) {
1666
                        return (void *) r;      /* silence the warning */
1667
                }
1668
                --np;
1669
        }
1670
 
1671
        return NULL;
1672
}
1673
#undef np
1674
 
1675
#endif
1676
/**********************************************************************/
1677
#ifdef L_wcpcpy
1678
#define L_stpcpy
1679
#define Wstpcpy wcpcpy
1680
#else
1681
#define Wstpcpy stpcpy
1682
#endif
1683
 
1684
#ifdef L_stpcpy
1685
 
1686
Wchar *Wstpcpy(register Wchar * __restrict s1, const Wchar * __restrict s2)
1687
{
1688
#ifdef __BCC__
1689
        do {
1690
                *s1 = *s2++;
1691
        } while (*s1++ != 0);
1692
#else
1693
        while ( (*s1++ = *s2++) != 0 );
1694
#endif
1695
 
1696
        return s1 - 1;
1697
}
1698
 
1699
#endif
1700
/**********************************************************************/
1701
#ifdef L_wcpncpy
1702
#define L_stpncpy
1703
#define Wstpncpy wcpncpy
1704
#else
1705
#define Wstpncpy stpncpy
1706
#endif
1707
 
1708
#ifdef L_stpncpy
1709
 
1710
Wchar *Wstpncpy(register Wchar * __restrict s1,
1711
                                register const Wchar * __restrict s2,
1712
                                size_t n)
1713
{
1714
        Wchar *s = s1;
1715
        const Wchar *p = s2;
1716
 
1717
#ifdef __BCC__
1718
        while (n--) {
1719
                if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
1720
                ++s;
1721
        }
1722
        return s1 + (s2 - p);
1723
#else
1724
        while (n) {
1725
                if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
1726
                ++s;
1727
                --n;
1728
        }
1729
        return s1 + (s2 - p);
1730
#endif
1731
}
1732
 
1733
#endif
1734
/**********************************************************************/
1735
#ifdef L_bzero
1736
 
1737
void bzero(void *s, size_t n)
1738
{
1739
        register unsigned char *p = s;
1740
#ifdef __BCC__
1741
        /* bcc can optimize the counter if it thinks it is a pointer... */
1742
        register const char *np = (const char *) n;
1743
#else
1744
#define np n
1745
#endif
1746
 
1747
        while (np) {
1748
                *p++ = 0;
1749
                --np;
1750
        }
1751
}
1752
#undef np
1753
 
1754
#endif
1755
/**********************************************************************/
1756
#ifdef L_bcopy
1757
 
1758
void bcopy(const void *s2, void *s1, size_t n)
1759
{
1760
#if 1
1761
        memmove(s1, s2, n);
1762
#else
1763
#ifdef __BCC__
1764
        register char *s;
1765
        register const char *p;
1766
 
1767
        s = s1;
1768
        p = s2;
1769
        if (p >= s) {
1770
                while (n--) {
1771
                        *s++ = *p++;
1772
                }
1773
        } else {
1774
                s += n;
1775
                p += n;
1776
                while (n--) {
1777
                        *--s = *--p;
1778
                }
1779
        }
1780
#else
1781
        register char *s;
1782
        register const char *p;
1783
 
1784
        s = s1;
1785
        p = s2;
1786
        if (p >= s) {
1787
                while (n) {
1788
                        *s++ = *p++;
1789
                        --n;
1790
                }
1791
        } else {
1792
                while (n) {
1793
                        --n;
1794
                        s[n] = p[n];
1795
                }
1796
        }
1797
#endif
1798
#endif
1799
}
1800
 
1801
#endif
1802
/**********************************************************************/
1803
#ifdef L_strcasestr
1804
 
1805
char *strcasestr(const char *s1, const char *s2)
1806
{
1807
        register const char *s = s1;
1808
        register const char *p = s2;
1809
 
1810
#if 1
1811
        do {
1812
                if (!*p) {
1813
                        return (char *) s1;;
1814
                }
1815
                if ((*p == *s)
1816
                        || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
1817
                        ) {
1818
                        ++p;
1819
                        ++s;
1820
                } else {
1821
                        p = s2;
1822
                        if (!*s) {
1823
                                return NULL;
1824
                        }
1825
                        s = ++s1;
1826
                }
1827
        } while (1);
1828
#else
1829
        while (*p && *s) {
1830
                if ((*p == *s)
1831
                        || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
1832
                        ) {
1833
                        ++p;
1834
                        ++s;
1835
                } else {
1836
                        p = s2;
1837
                        s = ++s1;
1838
                }
1839
        }
1840
 
1841
        return (*p) ? NULL : (char *) s1;
1842
#endif
1843
}
1844
 
1845
#endif
1846
/**********************************************************************/
1847
#ifdef L_strndup
1848
 
1849
char *strndup(register const char *s1, size_t n)
1850
{
1851
        register char *s;
1852
 
1853
        n = strnlen(s1,n);                      /* Avoid problems if s1 not nul-terminated. */
1854
 
1855
    if ((s = malloc(n + 1)) != NULL) {
1856
                memcpy(s, s1, n);
1857
                s[n] = 0;
1858
        }
1859
 
1860
        return s;
1861
}
1862
 
1863
#endif
1864
/**********************************************************************/
1865
#ifdef L_strsep
1866
 
1867
char *strsep(char ** __restrict s1, const char * __restrict s2)
1868
{
1869
        register char *s = *s1;
1870
        register char *p;
1871
 
1872
#if 1
1873
        p = NULL;
1874
        if (s && *s && (p = strpbrk(s, s2))) {
1875
                *p++ = 0;
1876
        }
1877
#else
1878
        if (s && *s && *(p = s + strcspn(s, s2))) {
1879
                *p++ = 0;
1880
        } else {
1881
                p = NULL;
1882
        }
1883
#endif
1884
        *s1 = p;
1885
        return s;
1886
}
1887
 
1888
#endif
1889
/**********************************************************************/
1890
#ifdef L_wcschrnul
1891
#define L_strchrnul
1892
#define __Wstrchrnul __wcschrnul
1893
#define Wstrchrnul wcschrnul
1894
#else
1895
#define __Wstrchrnul __strchrnul
1896
#define Wstrchrnul strchrnul
1897
#endif
1898
 
1899
#ifdef L_strchrnul
1900
 
1901
extern Wchar *__Wstrchrnul(register const Wchar *s, Wint c);
1902
weak_alias(__Wstrchrnul, Wstrchrnul);
1903
 
1904
Wchar *__Wstrchrnul(register const Wchar *s, Wint c)
1905
{
1906
        --s;
1907
        while (*++s && (*s != ((Wchar)c)));
1908
        return (Wchar *) s;
1909
}
1910
 
1911
#endif
1912
/**********************************************************************/
1913
#ifdef L_rawmemchr
1914
 
1915
void *rawmemchr(const void *s, int c)
1916
{
1917
        register const unsigned char *r = s;
1918
 
1919
        while (*r != ((unsigned char)c)) ++r;
1920
 
1921
        return (void *) r;      /* silence the warning */
1922
}
1923
 
1924
#endif
1925
/**********************************************************************/
1926
#ifdef L_basename
1927
 
1928
char *basename(const char *path)
1929
{
1930
        register const char *s;
1931
        register const char *p;
1932
 
1933
        p = s = path;
1934
 
1935
        while (*s) {
1936
                if (*s++ == '/') {
1937
                        p = s;
1938
                }
1939
        }
1940
 
1941
        return (char *) p;
1942
}
1943
 
1944
#endif
1945
/**********************************************************************/
1946
#ifdef L___xpg_basename
1947
 
1948
char *__xpg_basename(register char *path)
1949
{
1950
        static const char null_or_empty[] = ".";
1951
        char *first;
1952
        register char *last;
1953
 
1954
        first = (char *) null_or_empty;
1955
 
1956
        if (path && *path) {
1957
                first = path;
1958
                last = path - 1;
1959
 
1960
                do {
1961
                        if ((*path != '/') && (path > ++last)) {
1962
                                last = first = path;
1963
                        }
1964
                } while (*++path);
1965
 
1966
                if (*first == '/') {
1967
                        last = first;
1968
                }
1969
                last[1] = 0;
1970
        }
1971
 
1972
        return first;
1973
}
1974
 
1975
#endif
1976
/**********************************************************************/
1977
#ifdef L_dirname
1978
 
1979
char *dirname(char *path)
1980
{
1981
        static const char null_or_empty_or_noslash[] = ".";
1982
        register char *s;
1983
        register char *last;
1984
        char *first;
1985
 
1986
        last = s = path;
1987
 
1988
        if (s != NULL) {
1989
 
1990
        LOOP:
1991
                while (*s && (*s != '/')) ++s;
1992
                first = s;
1993
                while (*s == '/') ++s;
1994
                if (*s) {
1995
                        last = first;
1996
                        goto LOOP;
1997
                }
1998
 
1999
                if (last == path) {
2000
                        if (*last != '/') {
2001
                                goto DOT;
2002
                        }
2003
                        if ((*++last == '/') && (last[1] == 0)) {
2004
                                ++last;
2005
                        }
2006
                }
2007
                *last = 0;
2008
                return path;
2009
        }
2010
 DOT:
2011
        return (char *) null_or_empty_or_noslash;
2012
}
2013
 
2014
#endif
2015
/**********************************************************************/
2016
#ifdef L_strlcat
2017
 
2018
/* OpenBSD function:
2019
 * Append at most n-1-strlen(dst) chars from src to dst and nul-terminate dst.
2020
 * Returns strlen(src) + strlen({original} dst), so truncation occurred if the
2021
 * return val is >= n.
2022
 * Note: If dst doesn't contain a nul in the first n chars, strlen(dst) is
2023
 *       taken as n. */
2024
 
2025
size_t strlcat(register char *__restrict dst,
2026
                           register const char *__restrict src,
2027
                           size_t n)
2028
{
2029
        size_t len;
2030
        char dummy[1];
2031
 
2032
        len = 0;
2033
 
2034
        while (1) {
2035
                if (len >= n) {
2036
                        dst = dummy;
2037
                        break;
2038
                }
2039
                if (!*dst) {
2040
                        break;
2041
                }
2042
                ++dst;
2043
                ++len;
2044
        }
2045
 
2046
        while ((*dst = *src) != 0) {
2047
                if (++len < n) {
2048
                        ++dst;
2049
                }
2050
                ++src;
2051
        }
2052
 
2053
        return len;
2054
}
2055
 
2056
#endif
2057
/**********************************************************************/
2058
#ifdef WANT_WIDE
2059
extern size_t __wcslcpy(wchar_t *__restrict dst,
2060
                                                const wchar_t *__restrict src,
2061
                                                size_t n);
2062
#endif
2063
 
2064
 
2065
#ifdef L___wcslcpy
2066
#define L_strlcpy
2067
#define Wstrlcpy __wcslcpy
2068
#ifdef __LOCALE_C_ONLY
2069
weak_alias(__wcslcpy,wcsxfrm);
2070
#endif
2071
#endif
2072
 
2073
#ifdef L_strlcpy
2074
 
2075
#ifndef L___wcslcpy
2076
#define Wstrlcpy strlcpy
2077
#ifdef __LOCALE_C_ONLY
2078
weak_alias(strlcpy,strxfrm);
2079
#endif
2080
#endif
2081
 
2082
/* OpenBSD function:
2083
 * Copy at most n-1 chars from src to dst and nul-terminate dst.
2084
 * Returns strlen(src), so truncation occurred if the return value is >= n. */
2085
 
2086
size_t Wstrlcpy(register Wchar *__restrict dst,
2087
                                  register const Wchar *__restrict src,
2088
                                  size_t n)
2089
{
2090
        const Wchar *src0 = src;
2091
        Wchar dummy[1];
2092
 
2093
        if (!n) {
2094
                dst = dummy;
2095
        } else {
2096
                --n;
2097
        }
2098
 
2099
        while ((*dst = *src) != 0) {
2100
                if (n) {
2101
                        --n;
2102
                        ++dst;
2103
                }
2104
                ++src;
2105
        }
2106
 
2107
        return src - src0;
2108
}
2109
 
2110
#endif
2111
/**********************************************************************/
2112
#if defined(L__string_syssigmsgs) && defined(__UCLIBC_HAS_SIGNUM_MESSAGES__)
2113
 
2114
const char _string_syssigmsgs[] = {
2115
        /*   0:    0,  1 */ "\0"
2116
        /*   1:    1,  7 */ "Hangup\0"
2117
        /*   2:    8, 10 */ "Interrupt\0"
2118
        /*   3:   18,  5 */ "Quit\0"
2119
        /*   4:   23, 20 */ "Illegal instruction\0"
2120
        /*   5:   43, 22 */ "Trace/breakpoint trap\0"
2121
        /*   6:   65,  8 */ "Aborted\0"
2122
        /*   7:   73, 10 */ "Bus error\0"
2123
        /*   8:   83, 25 */ "Floating point exception\0"
2124
        /*   9:  108,  7 */ "Killed\0"
2125
        /*  10:  115, 22 */ "User defined signal 1\0"
2126
        /*  11:  137, 19 */ "Segmentation fault\0"
2127
        /*  12:  156, 22 */ "User defined signal 2\0"
2128
        /*  13:  178, 12 */ "Broken pipe\0"
2129
        /*  14:  190, 12 */ "Alarm clock\0"
2130
        /*  15:  202, 11 */ "Terminated\0"
2131
        /*  16:  213, 12 */ "Stack fault\0"
2132
        /*  17:  225, 13 */ "Child exited\0"
2133
        /*  18:  238, 10 */ "Continued\0"
2134
        /*  19:  248, 17 */ "Stopped (signal)\0"
2135
        /*  20:  265,  8 */ "Stopped\0"
2136
        /*  21:  273, 20 */ "Stopped (tty input)\0"
2137
        /*  22:  293, 21 */ "Stopped (tty output)\0"
2138
        /*  23:  314, 21 */ "Urgent I/O condition\0"
2139
        /*  24:  335, 24 */ "CPU time limit exceeded\0"
2140
        /*  25:  359, 25 */ "File size limit exceeded\0"
2141
        /*  26:  384, 22 */ "Virtual timer expired\0"
2142
        /*  27:  406, 24 */ "Profiling timer expired\0"
2143
        /*  28:  430, 15 */ "Window changed\0"
2144
        /*  29:  445, 13 */ "I/O possible\0"
2145
        /*  30:  458, 14 */ "Power failure\0"
2146
        /*  31:  472, 16 */ "Bad system call"
2147
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
2148
        /*  32:  488,  9 */ "\0EMT trap"
2149
#endif
2150
};
2151
 
2152
#endif
2153
 
2154
/**********************************************************************/
2155
#if defined(L_sys_siglist) && defined(__UCLIBC_HAS_SYS_SIGLIST__)
2156
 
2157
const char *const sys_siglist[_NSIG] = {
2158
        [0] =                            NULL,
2159
        [SIGHUP] =                      _string_syssigmsgs + 1,
2160
        [SIGINT] =                      _string_syssigmsgs + 8,
2161
        [SIGQUIT] =                     _string_syssigmsgs + 18,
2162
        [SIGILL] =                      _string_syssigmsgs + 23,
2163
        [SIGTRAP] =                     _string_syssigmsgs + 43,
2164
        [SIGABRT] =                     _string_syssigmsgs + 65,
2165
        [SIGBUS] =                      _string_syssigmsgs + 73,
2166
        [SIGFPE] =                      _string_syssigmsgs + 83,
2167
        [SIGKILL] =                     _string_syssigmsgs + 108,
2168
        [SIGUSR1] =                     _string_syssigmsgs + 115,
2169
        [SIGSEGV] =                     _string_syssigmsgs + 137,
2170
        [SIGUSR2] =                     _string_syssigmsgs + 156,
2171
        [SIGPIPE] =                     _string_syssigmsgs + 178,
2172
        [SIGALRM] =                     _string_syssigmsgs + 190,
2173
        [SIGTERM] =                     _string_syssigmsgs + 202,
2174
#if !(defined(__alpha__) || defined(__mips__) || defined(__sparc__))
2175
        [SIGSTKFLT] =           _string_syssigmsgs + 213,
2176
#endif
2177
        [SIGCHLD] =                     _string_syssigmsgs + 225,
2178
        [SIGCONT] =                     _string_syssigmsgs + 238,
2179
        [SIGSTOP] =                     _string_syssigmsgs + 248,
2180
        [SIGTSTP] =                     _string_syssigmsgs + 265,
2181
        [SIGTTIN] =                     _string_syssigmsgs + 273,
2182
        [SIGTTOU] =                     _string_syssigmsgs + 293,
2183
        [SIGURG] =                      _string_syssigmsgs + 314,
2184
        [SIGXCPU] =                     _string_syssigmsgs + 335,
2185
        [SIGXFSZ] =                     _string_syssigmsgs + 359,
2186
        [SIGVTALRM] =           _string_syssigmsgs + 384,
2187
        [SIGPROF] =                     _string_syssigmsgs + 406,
2188
        [SIGWINCH] =            _string_syssigmsgs + 430,
2189
        [SIGIO] =                       _string_syssigmsgs + 445,
2190
        [SIGPWR] =                      _string_syssigmsgs + 458,
2191
        [SIGSYS] =                      _string_syssigmsgs + 472,
2192
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
2193
        [SIGEMT] =                      _string_syssigmsgs + 488,
2194
#endif
2195
};
2196
 
2197
#endif
2198
/**********************************************************************/
2199
#ifdef L_strsignal
2200
 
2201
/* TODO: make a threadsafe version? */
2202
 
2203
#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
2204
 
2205
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
2206
static const unsigned char sstridx[] = {
2207
        0,
2208
        SIGHUP,
2209
        SIGINT,
2210
        SIGQUIT,
2211
        SIGILL,
2212
        SIGTRAP,
2213
        SIGIOT,
2214
        SIGBUS,
2215
        SIGFPE,
2216
        SIGKILL,
2217
        SIGUSR1,
2218
        SIGSEGV,
2219
        SIGUSR2,
2220
        SIGPIPE,
2221
        SIGALRM,
2222
        SIGTERM,
2223
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
2224
        0,
2225
#else
2226
        SIGSTKFLT,
2227
#endif
2228
        SIGCHLD,
2229
        SIGCONT,
2230
        SIGSTOP,
2231
        SIGTSTP,
2232
        SIGTTIN,
2233
        SIGTTOU,
2234
        SIGURG,
2235
        SIGXCPU,
2236
        SIGXFSZ,
2237
        SIGVTALRM,
2238
        SIGPROF,
2239
        SIGWINCH,
2240
        SIGIO,
2241
        SIGPWR,
2242
        SIGSYS,
2243
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
2244
        SIGEMT,
2245
#endif
2246
};
2247
#endif
2248
 
2249
char *strsignal(int signum)
2250
{
2251
    register char *s;
2252
    int i;
2253
    static char buf[_STRSIGNAL_BUFSIZE];
2254
    static const char unknown[] = {
2255
                'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
2256
    };
2257
 
2258
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
2259
        /* Need to translate signum to string index. */
2260
        for (i = 0 ; i < sizeof(sstridx)/sizeof(sstridx[0]) ; i++) {
2261
                if (sstridx[i] == signum) {
2262
                        goto GOT_SSTRIDX;
2263
                }
2264
        }
2265
        i = INT_MAX;    /* Failed. */
2266
 GOT_SSTRIDX:
2267
#else
2268
        /* No signum to string index translation needed. */
2269
        i = signum;
2270
#endif
2271
 
2272
    if (((unsigned int) signum) < _SYS_NSIG) {
2273
                /* Trade time for space.  This function should rarely be called
2274
                 * so rather than keeping an array of pointers for the different
2275
                 * messages, just run through the buffer until we find the
2276
                 * correct string. */
2277
                for (s = (char *) _string_syssigmsgs ; i ; ++s) {
2278
                        if (!*s) {
2279
                                --i;
2280
                        }
2281
                }
2282
                if (*s) {               /* Make sure we have an actual message. */
2283
                        goto DONE;
2284
                }
2285
    }
2286
 
2287
    s = _int10tostr(buf+sizeof(buf)-1, signum) - sizeof(unknown);
2288
    memcpy(s, unknown, sizeof(unknown));
2289
 
2290
 DONE:
2291
        return s;
2292
}
2293
 
2294
#else  /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
2295
 
2296
char *strsignal(int signum)
2297
{
2298
    static char buf[_STRSIGNAL_BUFSIZE];
2299
    static const char unknown[] = {
2300
                'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
2301
    };
2302
 
2303
    return (char *) memcpy(_int10tostr(buf+sizeof(buf)-1, signum)
2304
                                                   - sizeof(unknown),
2305
                                                   unknown, sizeof(unknown));
2306
}
2307
 
2308
#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
2309
 
2310
#endif
2311
/**********************************************************************/
2312
#ifdef L_psignal
2313
 
2314
/* TODO: make this threadsafe with a reentrant version of strsignal? */
2315
 
2316
void psignal(int signum, register const char *message)
2317
{
2318
        /* If the program is calling psignal, it's a safe bet that printf and
2319
         * friends are used as well.  It is also possible that the calling
2320
         * program could buffer stderr, or reassign it. */
2321
 
2322
        register const char *sep;
2323
 
2324
        sep = ": ";
2325
        if (!(message && *message)) { /* Caller did not supply a prefix message */
2326
                message = (sep += 2);   /* or passed an empty string. */
2327
        }
2328
 
2329
#if 1
2330
        fprintf(stderr, "%s%s%s\n", message, sep, strsignal(signum));
2331
#else
2332
        /* Note: Assumes stderr not closed or buffered. */
2333
        __STDIO_THREADLOCK(stderr);
2334
        _stdio_fdout(STDERR_FILENO, message, sep, strsignal(signum));
2335
        __STDIO_THREADUNLOCK(stderr);
2336
#endif
2337
}
2338
 
2339
#endif
2340
/**********************************************************************/
2341
#ifndef __LOCALE_C_ONLY
2342
#if defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l)
2343
 
2344
#ifdef L_strxfrm
2345
#ifndef WANT_WIDE
2346
#error WANT_WIDE should be defined for L_strxfrm
2347
#endif
2348
#ifdef L_wcsxfrm
2349
#error L_wcsxfrm already defined for L_strxfrm
2350
#endif
2351
#endif /* L_strxfrm */
2352
 
2353
#if defined(L_strxfrm) || defined(L_strxfrm_l)
2354
 
2355
#define wcscoll   strcoll
2356
#define wcscoll_l strcoll_l
2357
#define __wcscoll_l __strcoll_l
2358
#define wcsxfrm   strxfrm
2359
#define wcsxfrm_l strxfrm_l
2360
#define __wcsxfrm_l __strxfrm_l
2361
 
2362
#undef WANT_WIDE
2363
#undef Wvoid
2364
#undef Wchar
2365
#undef Wuchar
2366
#undef Wint
2367
 
2368
#define Wchar char
2369
 
2370
#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) */
2371
 
2372
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
2373
 
2374
int wcscoll (const Wchar *s0, const Wchar *s1)
2375
{
2376
        return __wcscoll_l(s0, s1, __UCLIBC_CURLOCALE );
2377
}
2378
 
2379
size_t wcsxfrm(Wchar *__restrict ws1, const Wchar *__restrict ws2, size_t n)
2380
{
2381
        return __wcsxfrm_l(ws1, ws2, n, __UCLIBC_CURLOCALE );
2382
}
2383
 
2384
#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
2385
 
2386
 
2387
#if 0
2388
#define CUR_COLLATE (&__UCLIBC_CURLOCALE_DATA.collate)
2389
#else
2390
#define CUR_COLLATE (& __LOCALE_PTR->collate)
2391
#endif
2392
 
2393
#define MAX_PENDING 8
2394
 
2395
typedef struct {
2396
        const Wchar *s;
2397
        const Wchar *eob;                       /* end of backward */
2398
 
2399
        __uwchar_t weight;
2400
        __uwchar_t ui_weight;           /* undefined or invalid */
2401
        int colitem;
2402
        int weightidx;
2403
        int rule;
2404
        size_t position;
2405
        /* should be wchar_t.  if wchar < 0 do EILSEQ? */
2406
        __uwchar_t *cip;
2407
        __uwchar_t ci_pending[MAX_PENDING];     /* nul-terminated */
2408
 
2409
        char *back_buf;
2410
        char *bbe;                                      /* end of back_buf (actual last... not 1 past end) */
2411
        char *bp;                                       /* ptr into backbuf, NULL if not in backward mode */
2412
        char ibb[128];
2413
        size_t bb_size;
2414
 
2415
        int ru_pushed;
2416
} col_state_t;
2417
 
2418
 
2419
#define WEIGHT_MASK     0x3fffU
2420
#define RULE_MASK       0xc000U
2421
 
2422
#define RULE_FORWARD  (1 << 14)
2423
#define RULE_POSITION (1 << 15)
2424
 
2425
#define UI_IDX          (WEIGHT_MASK-6)
2426
#define POSIT_IDX       (WEIGHT_MASK-5)
2427
#define RANGE_IDX       (WEIGHT_MASK-4)
2428
#define UNDEF_IDX       (WEIGHT_MASK-3)
2429
#define INVAL_IDX       (WEIGHT_MASK-2)
2430
#define DITTO_IDX   (WEIGHT_MASK-1)
2431
 
2432
 
2433
#undef TRACE
2434
#if 0
2435
#define TRACE(X)        printf X
2436
#else
2437
#define TRACE(X)        ((void)0)
2438
#endif
2439
 
2440
static int lookup(wchar_t wc   __LOCALE_PARAM )
2441
{
2442
        unsigned int sc, n, i0, i1;
2443
 
2444
        if (((__uwchar_t) wc) > 0xffffU) {
2445
                return 0;
2446
        }
2447
 
2448
        sc = wc & CUR_COLLATE->ti_mask;
2449
        wc >>= CUR_COLLATE->ti_shift;
2450
        n = wc & CUR_COLLATE->ii_mask;
2451
        wc >>= CUR_COLLATE->ii_shift;
2452
 
2453
        i0 = CUR_COLLATE->wcs2colidt_tbl[wc];
2454
        i0 <<= CUR_COLLATE->ii_shift;
2455
        i1 = CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + i0 + n];
2456
        i1 <<= CUR_COLLATE->ti_shift;
2457
        return CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + CUR_COLLATE->ti_len + i1 + sc];
2458
 
2459
}
2460
 
2461
static void init_col_state(col_state_t *cs, const Wchar *wcs)
2462
{
2463
        memset(cs, 0, sizeof(col_state_t));
2464
        cs->s = wcs;
2465
        cs->bp = cs->back_buf = cs->ibb;
2466
        cs->bb_size = 128;
2467
        cs->bbe = cs->back_buf + (cs->bb_size -1);
2468
}
2469
 
2470
static void next_weight(col_state_t *cs, int pass   __LOCALE_PARAM )
2471
{
2472
        int r, w, ru, ri, popping_backup_stack;
2473
        ssize_t n;
2474
        const uint16_t *p;
2475
#ifdef WANT_WIDE
2476
#define WC (*cs->s)
2477
#define N (1)
2478
#else  /* WANT_WIDE */
2479
        wchar_t WC;
2480
        size_t n0, nx;
2481
#define N n0
2482
 
2483
#endif /* WANT_WIDE */
2484
 
2485
        do {
2486
 
2487
                if (cs->ru_pushed) {
2488
                        ru = cs->ru_pushed;
2489
                        TRACE(("ru_pushed = %d\n", ru));
2490
                        cs->ru_pushed = 0;
2491
                        goto POSITION_SKIP;
2492
                }
2493
 
2494
#ifdef __UCLIBC_MJN3_ONLY__
2495
#warning should we walk pendings backwards?
2496
#endif
2497
                if (cs->cip) {                  /* possible pending weight */
2498
                        if ((r = *(cs->cip++)) == 0) {
2499
                                cs->cip = NULL;
2500
                                continue;
2501
                        }
2502
                        cs->weightidx = r & WEIGHT_MASK;
2503
                        assert(cs->weightidx);
2504
/*                      assert(cs->weightidx != WEIGHT_MASK); */
2505
                } else {                                /* get the next collation item from the string */
2506
                        TRACE(("clearing popping flag\n"));
2507
                        popping_backup_stack = 0;
2508
 
2509
                IGNORE_LOOP:
2510
                        /* keep first pos as 0 for a sentinal */
2511
                        if (*cs->bp) {                          /* pending backward chars */
2512
                        POP_BACKUP:
2513
                                popping_backup_stack = 1;
2514
                                TRACE(("setting popping flag\n"));
2515
                                n = 0;
2516
                                if (*cs->bp > 0) {               /* singles pending */
2517
                                        cs->s -= 1;
2518
                                        if ((*cs->bp -= 1) == 0) {
2519
                                                cs->bp -= 1;
2520
                                        }
2521
                                } else {                                /* last was a multi */
2522
                                        cs->s += *cs->bp;
2523
                                        cs->bp -= 1;
2524
                                }
2525
                        } else if (!*cs->s) { /* not in backward mode and end of string */
2526
                                cs->weight = 0;
2527
                                return;
2528
                        } else {
2529
                                cs->position += 1;
2530
                        }
2531
 
2532
                BACK_LOOP:
2533
#ifdef WANT_WIDE
2534
                        n = 1;
2535
                        cs->colitem = r = lookup(*cs->s   __LOCALE_ARG );
2536
#else  /* WANT_WIDE */
2537
                        n = n0 = __locale_mbrtowc_l(&WC, cs->s, __LOCALE_PTR);
2538
                        if (n < 0) {
2539
                                __set_errno(EILSEQ);
2540
                                cs->weight = 0;
2541
                                return;
2542
                        }
2543
                        cs->colitem = r = lookup(WC   __LOCALE_ARG );
2544
#endif /* WANT_WIDE */
2545
 
2546
                        TRACE((" r=%d WC=%#lx\n", r, (unsigned long)(WC)));
2547
 
2548
                        if (r > CUR_COLLATE->max_col_index) { /* starting char for one or more sequences */
2549
                                p = CUR_COLLATE->multistart_tbl;
2550
                                p += p[r-CUR_COLLATE->max_col_index -1];
2551
                                do {
2552
                                        n = N;
2553
                                        r = *p++;
2554
                                        do {
2555
                                                if (!*p) {              /* found it */
2556
                                                        cs->colitem = r;
2557
                                                        TRACE(("    found multi %d\n", n));
2558
                                                        goto FOUND;
2559
                                                }
2560
#ifdef WANT_WIDE
2561
                                                /* the lookup check here is safe since we're assured that *p is a valid colidx */
2562
                                                if (!cs->s[n] || (lookup(cs->s[n]   __LOCALE_ARG ) != *p)) {
2563
                                                        do {} while (*p++);
2564
                                                        break;
2565
                                                }
2566
                                                ++p;
2567
                                                ++n;
2568
#else  /* WANT_WIDE */
2569
                                                if (cs->s[n]) {
2570
                                                        nx = __locale_mbrtowc_l(&WC, cs->s + n, __LOCALE_PTR);
2571
                                                        if (nx < 0) {
2572
                                                                __set_errno(EILSEQ);
2573
                                                                cs->weight = 0;
2574
                                                                return;
2575
                                                        }
2576
                                                }
2577
                                                if (!cs->s[n] || (lookup(WC   __LOCALE_ARG ) != *p)) {
2578
                                                        do {} while (*p++);
2579
                                                        break;
2580
                                                }
2581
                                                ++p;
2582
                                                n += nx; /* Only gets here if cs->s[n] != 0, so nx is set. */
2583
#endif /* WANT_WIDE */
2584
                                        } while (1);
2585
                                } while (1);
2586
                        } else if (r == 0) {             /* illegal, undefined, or part of a range */
2587
                                if ((CUR_COLLATE->range_count)
2588
#ifdef __UCLIBC_MJN3_ONLY__
2589
#warning .. need to introduce range as a collating item?
2590
#endif
2591
                                        && (((__uwchar_t)(WC - CUR_COLLATE->range_low)) <= CUR_COLLATE->range_count)
2592
                                        ) {                                     /* part of a range */
2593
                                        /* Note: cs->colitem = 0 already. */
2594
                                        TRACE(("    found range\n"));
2595
                                        ru = CUR_COLLATE->ruletable[CUR_COLLATE->range_rule_offset*CUR_COLLATE->MAX_WEIGHTS + pass];
2596
                                        assert((ru & WEIGHT_MASK) != DITTO_IDX);
2597
                                        if ((ru & WEIGHT_MASK) == WEIGHT_MASK) {
2598
                                                ru = (ru & RULE_MASK) | RANGE_IDX;
2599
                                                cs->weight = CUR_COLLATE->range_base_weight + (WC - CUR_COLLATE->range_low);
2600
                                        }
2601
                                        goto RANGE_SKIP_TO;
2602
                                } else if (((__uwchar_t)(WC)) <= 0x7fffffffUL) { /* legal but undefined */
2603
                                UNDEFINED:
2604
                                        /* Note: cs->colitem = 0 already. */
2605
                                        ri = CUR_COLLATE->undefined_idx;
2606
                                        assert(ri != 0); /* implicit undefined isn't supported */
2607
 
2608
                                        TRACE(("    found explicit UNDEFINED\n"));
2609
#ifdef __UCLIBC_MJN3_ONLY__
2610
#warning right now single weight locales do not support ..
2611
#endif
2612
                                        if (CUR_COLLATE->num_weights == 1) {
2613
                                                TRACE(("    single weight UNDEFINED\n"));
2614
                                                cs->weightidx = RANGE_IDX;
2615
                                                cs->weight = ri;
2616
                                                cs->s += n;
2617
                                                goto PROCESS_WEIGHT;
2618
                                        }
2619
 
2620
                                        ri = CUR_COLLATE->index2ruleidx[ri - 1];
2621
                                        ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass];
2622
                                        assert((ru & WEIGHT_MASK) != WEIGHT_MASK); /* TODO: handle ".." */
2623
                                        if ((ru & WEIGHT_MASK) == DITTO_IDX) {
2624
                                                cs->colitem = CUR_COLLATE->undefined_idx;
2625
                                        }
2626
                                        goto RANGE_SKIP_TO;
2627
                                } else {                /* illegal */
2628
                                        TRACE(("    found illegal\n"));
2629
                                        __set_errno(EINVAL);
2630
                                        /* We put all illegals in the same equiv class with maximal weight,
2631
                                         * and ignore them after the first pass. */
2632
                                        if (pass > 0) {
2633
                                                cs->s += n;
2634
                                                goto IGNORE_LOOP;
2635
                                        }
2636
                                        ru = (RULE_FORWARD | RANGE_IDX);
2637
                                        cs->weight = 0xffffU;
2638
                                        goto RANGE_SKIP_TO;
2639
                                }
2640
                        } else if (CUR_COLLATE->num_weights == 1) {
2641
                                TRACE(("    single weight\n"));
2642
                                cs->weightidx = RANGE_IDX;
2643
                                cs->weight = cs->colitem;
2644
                                cs->s += n;
2645
                                goto PROCESS_WEIGHT;
2646
                        } else {
2647
                                TRACE(("    normal\n"));
2648
                        }
2649
 
2650
                        /* if we get here, it is a normal char either singlely weighted, undefined, or in a range */
2651
                FOUND:
2652
                        ri = CUR_COLLATE->index2ruleidx[cs->colitem - 1];
2653
                        TRACE((" ri=%d ", ri));
2654
#ifdef __UCLIBC_MJN3_ONLY__
2655
#warning make sure this is correct
2656
#endif
2657
                        if (!ri) {
2658
                                TRACE(("NOT IN THIS LOCALE\n"));
2659
                                goto UNDEFINED;
2660
                        }
2661
                        ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass];
2662
 
2663
                RANGE_SKIP_TO:
2664
 
2665
#ifdef __UCLIBC_MJN3_ONLY__
2666
#warning ignoreables probably should not interrupt backwards processing, but this is wrong
2667
#endif
2668
/*                      if (!(ru & WEIGHT_MASK)) { */
2669
/*                              TRACE(("IGNORE\n")); */
2670
/*                              cs->s += n; */
2671
/*                              continue; */
2672
/*                      } */
2673
 
2674
 
2675
                        TRACE((" rule = %#x  weight = %#x  popping = %d  s = %p  eob = %p\n",
2676
                                   ru & RULE_MASK, ru & WEIGHT_MASK, popping_backup_stack,
2677
                                   cs->s, cs->eob));
2678
                        /* now we need to check if we're going backwards... */
2679
 
2680
                        if (!popping_backup_stack) {
2681
                                if (!(ru & RULE_MASK)) { /* backward */
2682
                                        TRACE(("backwards\n"));
2683
                                        assert(cs->bp <= cs->bbe);
2684
                                        if (cs->bp == cs->bbe) {
2685
                                                if (cs->back_buf == cs->ibb) { /* was using internal buffer */
2686
                                                        cs->bp = malloc(cs->bb_size + 128);
2687
                                                        if (!cs->bp) {
2688
                                                                __set_errno(ENOMEM);
2689
#ifdef __UCLIBC_MJN3_ONLY__
2690
#warning what to do here?
2691
#endif
2692
                                                                cs->weight = 0;
2693
                                                                return;
2694
                                                        }
2695
                                                        memcpy(cs->bp, cs->back_buf, cs->bb_size);
2696
 
2697
                                                } else {
2698
                                                        cs->bp = realloc(cs->back_buf, cs->bb_size + 128);
2699
                                                        if (!cs->bp) {
2700
                                                                __set_errno(ENOMEM);
2701
#ifdef __UCLIBC_MJN3_ONLY__
2702
#warning what to do here?
2703
#endif
2704
                                                                cs->weight = 0;
2705
                                                                return;
2706
                                                        }
2707
                                                }
2708
                                                cs->bb_size += 128;
2709
                                                cs->bbe = cs->bp + (cs->bbe - cs->back_buf);
2710
                                                cs->back_buf = cs->bp;
2711
                                                cs->bp = cs->bbe;
2712
 
2713
                                        }
2714
                                        if (n==1) {                     /* single char */
2715
                                                if (*cs->bp && (((unsigned char)(*cs->bp)) < CHAR_MAX)) {
2716
                                                        *cs->bp += 1; /* increment last single's count */
2717
                                                } else {          /* last was a multi, or just starting */
2718
                                                        if (!cs->bp) {
2719
                                                                cs->bp = cs->back_buf;
2720
                                                        } else {
2721
                                                                assert(cs->bp < cs->bbe);
2722
                                                                ++cs->bp;
2723
                                                        }
2724
                                                        *cs->bp = 1;
2725
                                                }
2726
                                        } else {                        /* multichar */
2727
                                                assert(n>1);
2728
                                                assert(cs->bp < cs->bbe);
2729
                                                *++cs->bp = -n;
2730
                                        }
2731
                                        cs->s += n;
2732
                                        if (*cs->s) {
2733
                                                goto BACK_LOOP;
2734
                                        }
2735
                                        /* end-of-string so start popping */
2736
                                        cs->eob = cs->s;
2737
                                        TRACE(("popping\n"));
2738
                                        goto POP_BACKUP;
2739
                                } else if (*cs->bp) { /* was going backward but this element isn't */
2740
                                        /* discard current and use previous backward element */
2741
                                        assert(!cs->cip);
2742
                                        cs->eob = cs->s;
2743
                                        TRACE(("popping\n"));
2744
                                        goto POP_BACKUP;
2745
                                } else {                                /* was and still going forward */
2746
                                        TRACE(("forwards\n"));
2747
                                        if ((ru & (RULE_POSITION|WEIGHT_MASK)) > RULE_POSITION) {
2748
                                                assert(ru & WEIGHT_MASK);
2749
                                                cs->ru_pushed = ru;
2750
                                                cs->weight = cs->position;
2751
#ifdef __UCLIBC_MJN3_ONLY__
2752
#warning devel code
2753
#endif
2754
                                                cs->position = 0;        /* reset to reduce size for strcoll? */
2755
                                                cs->s += n;
2756
                                                cs->weightidx = RANGE_IDX;
2757
                                                goto PROCESS_WEIGHT;
2758
                                        }
2759
                                }
2760
                        } else {                                        /* popping backwards stack */
2761
                                TRACE(("popping (continued)\n"));
2762
                                if (!*cs->bp) {
2763
                                        cs->s = cs->eob;
2764
                                }
2765
                                cs->s -= n;
2766
                        }
2767
 
2768
                        cs->s += n;
2769
                POSITION_SKIP:
2770
                        cs->weightidx = ru & WEIGHT_MASK;
2771
                        cs->rule = ru & RULE_MASK;
2772
                }
2773
 
2774
#ifdef __UCLIBC_MJN3_ONLY__
2775
#warning for pending we only want the weight... _not_ the rule
2776
#endif
2777
                if (!cs->weightidx) {   /* ignore */
2778
                        continue;
2779
                }
2780
 
2781
        PROCESS_WEIGHT:
2782
                assert(cs->weightidx);
2783
 
2784
 
2785
                if (((unsigned int)(cs->weightidx - UI_IDX)) <= (INVAL_IDX-UI_IDX)) {
2786
                        if (cs->weightidx == UI_IDX) {
2787
                                cs->weight = cs->ui_weight;
2788
                        }
2789
                        return;
2790
                }
2791
 
2792
                assert(cs->weightidx != WEIGHT_MASK);
2793
                if (cs->weightidx == DITTO_IDX) { /* want the weight of the current collating item */
2794
                        TRACE(("doing ditto\n"));
2795
                        w = CUR_COLLATE->index2weight[cs->colitem -1];
2796
                } else if (cs->weightidx <= CUR_COLLATE->max_col_index) { /* normal */
2797
                        TRACE(("doing normal\n"));
2798
                        w = CUR_COLLATE->index2weight[cs->weightidx -1];
2799
                } else {                                /* a string */
2800
                        TRACE(("doing string\n"));
2801
                        assert(!(cs->weightidx & RULE_MASK));
2802
                        /* note: iso14561 allows null string here */
2803
                        p = CUR_COLLATE->weightstr + (cs->weightidx - (CUR_COLLATE->max_col_index + 2));
2804
                        if (*p & WEIGHT_MASK) {
2805
                                r = 0;
2806
                                do {
2807
                                        assert(r < MAX_PENDING);
2808
                                        cs->ci_pending[r++] = *p++;
2809
                                } while (*p & WEIGHT_MASK);
2810
                                cs->cip = cs->ci_pending;
2811
                        }
2812
                        continue;
2813
                }
2814
 
2815
                cs->weight = w;
2816
                return;
2817
        } while (1);
2818
}
2819
 
2820
int __XL(wcscoll) (const Wchar *s0, const Wchar *s1   __LOCALE_PARAM )
2821
{
2822
        col_state_t ws[2];
2823
        int pass;
2824
 
2825
        if (!CUR_COLLATE->num_weights) { /* C locale */
2826
#ifdef WANT_WIDE
2827
                return wcscmp(s0, s1);
2828
#else  /* WANT_WIDE */
2829
                return strcmp(s0, s1);
2830
#endif /* WANT_WIDE */
2831
        }
2832
 
2833
        pass = 0;
2834
        do {                                            /* loop through the weights levels */
2835
                init_col_state(ws, s0);
2836
                init_col_state(ws+1, s1);
2837
                do {                                    /* loop through the strings */
2838
                        /* for each string, get the next weight */
2839
                        next_weight(ws, pass   __LOCALE_ARG );
2840
                        next_weight(ws+1, pass   __LOCALE_ARG );
2841
                        TRACE(("w0=%lu  w1=%lu\n",
2842
                                   (unsigned long) ws[0].weight,
2843
                                   (unsigned long) ws[1].weight));
2844
 
2845
                        if (ws[0].weight != ws[1].weight) {
2846
                                return ws[0].weight - ws[1].weight;
2847
                        }
2848
                } while (ws[0].weight);
2849
        } while (++pass < CUR_COLLATE->num_weights);
2850
 
2851
        return 0;
2852
}
2853
 
2854
__XL_ALIAS(wcscoll)
2855
 
2856
#ifdef WANT_WIDE
2857
 
2858
size_t __XL(wcsxfrm)(wchar_t *__restrict ws1, const wchar_t *__restrict ws2,
2859
                                         size_t n   __LOCALE_PARAM )
2860
{
2861
        col_state_t cs;
2862
        size_t count;
2863
        int pass;
2864
 
2865
        if (!CUR_COLLATE->num_weights) { /* C locale */
2866
                return __wcslcpy(ws1, ws2, n);
2867
        }
2868
 
2869
#ifdef __UCLIBC_MJN3_ONLY__
2870
#warning handle empty string as a special case
2871
#endif
2872
 
2873
        count = pass = 0;
2874
        do {                                            /* loop through the weights levels */
2875
                init_col_state(&cs, ws2);
2876
                do {                                    /* loop through the string */
2877
                        next_weight(&cs, pass   __LOCALE_ARG );
2878
                        TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight));
2879
                        if (count < n) {
2880
                                ws1[count] = cs.weight +1;
2881
                        }
2882
                        ++count;
2883
                        TRACE(("--------------------------------------------\n"));
2884
                } while (cs.weight);
2885
                if (count <= n) {               /* overwrite the trailing 0 end-of-pass marker */
2886
                        ws1[count-1] = 1;
2887
                }
2888
                TRACE(("--------------------  pass %d  --------------------\n", pass));
2889
        } while (++pass < CUR_COLLATE->num_weights);
2890
        if (count <= n) {                       /* oops... change it back */
2891
                ws1[count-1] = 0;
2892
        }
2893
        return count-1;
2894
}
2895
 
2896
__XL_ALIAS(wcsxfrm)
2897
 
2898
#else  /* WANT_WIDE */
2899
 
2900
static const unsigned long bound[] = {
2901
        1UL << 7,
2902
        1UL << 11,
2903
        1UL << 16,
2904
        1UL << 21,
2905
        1UL << 26,
2906
};
2907
 
2908
static unsigned char first[] = {
2909
        0x0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
2910
};
2911
 
2912
/* Use an extension of UTF-8 to store a 32 bit val in max 6 bytes. */
2913
 
2914
static size_t store(unsigned char *s, size_t count, size_t n, __uwchar_t weight)
2915
{
2916
        int i, r;
2917
 
2918
        i = 0;
2919
        do {
2920
                if (weight < bound[i]) {
2921
                        break;
2922
                }
2923
        } while (++i < sizeof(bound)/sizeof(bound[0]));
2924
 
2925
        r = i+1;
2926
        if (i + count < n) {
2927
                s += count;
2928
                s[0] = first[i];
2929
                while (i) {
2930
                        s[i] = 0x80 | (weight & 0x3f);
2931
                        weight >>= 6;
2932
                        --i;
2933
                }
2934
                s[0] |= weight;
2935
        }
2936
 
2937
        return r;
2938
}
2939
 
2940
size_t __XL(strxfrm)(char *__restrict ws1, const char *__restrict ws2, size_t n
2941
                                         __LOCALE_PARAM )
2942
{
2943
        col_state_t cs;
2944
        size_t count, inc;
2945
        int pass;
2946
 
2947
        if (!CUR_COLLATE->num_weights) { /* C locale */
2948
                return strlcpy(ws1, ws2, n);
2949
        }
2950
 
2951
#ifdef __UCLIBC_MJN3_ONLY__
2952
#warning handle empty string as a special case
2953
#endif
2954
 
2955
        inc = count = pass = 0;
2956
        do {                                            /* loop through the weights levels */
2957
                init_col_state(&cs, ws2);
2958
                do {                                    /* loop through the string */
2959
                        next_weight(&cs, pass   __LOCALE_ARG );
2960
                        TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight));
2961
                        inc = store((unsigned char *)ws1, count, n, cs.weight + 1);
2962
                        count += inc;
2963
                        TRACE(("--------------------------------------------\n"));
2964
                } while (cs.weight);
2965
                /* overwrite the trailing 0 end-of-pass marker */
2966
                assert(inc == 1);
2967
                if (count <= n) {
2968
                        ws1[count-1] = 1;
2969
                }
2970
                TRACE(("--------------------  pass %d  --------------------\n", pass));
2971
        } while (++pass < CUR_COLLATE->num_weights);
2972
        if (count <= n) {                       /* oops... change it back */
2973
                ws1[count-1] = 0;
2974
        }
2975
        return count-1;
2976
}
2977
 
2978
__XL_ALIAS(strxfrm)
2979
 
2980
#endif /* WANT_WIDE */
2981
 
2982
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
2983
 
2984
#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) */
2985
 
2986
#endif /* __LOCALE_C_ONLY */
2987
/**********************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.