diff options
Diffstat (limited to 'firmware/libc')
30 files changed, 2779 insertions, 0 deletions
diff --git a/firmware/libc/atoi.c b/firmware/libc/atoi.c new file mode 100644 index 0000000000..3393839b27 --- /dev/null +++ b/firmware/libc/atoi.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Gary Czvitkovicz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include "ctype.h" | ||
24 | |||
25 | int atoi (const char *str) | ||
26 | { | ||
27 | int value = 0; | ||
28 | int sign = 1; | ||
29 | |||
30 | while (isspace(*str)) | ||
31 | { | ||
32 | str++; | ||
33 | } | ||
34 | |||
35 | if ('-' == *str) | ||
36 | { | ||
37 | sign = -1; | ||
38 | str++; | ||
39 | } | ||
40 | else if ('+' == *str) | ||
41 | { | ||
42 | str++; | ||
43 | } | ||
44 | |||
45 | while ('0' == *str) | ||
46 | { | ||
47 | str++; | ||
48 | } | ||
49 | |||
50 | while (isdigit(*str)) | ||
51 | { | ||
52 | value = (value * 10) + (*str - '0'); | ||
53 | str++; | ||
54 | } | ||
55 | |||
56 | return value * sign; | ||
57 | } | ||
diff --git a/firmware/libc/ctype.c b/firmware/libc/ctype.c new file mode 100644 index 0000000000..6e9b4eb601 --- /dev/null +++ b/firmware/libc/ctype.c | |||
@@ -0,0 +1,22 @@ | |||
1 | #include <ctype.h> | ||
2 | |||
3 | const unsigned char _ctype_[257]={ | ||
4 | 0, | ||
5 | _C, _C, _C, _C, _C, _C, _C, _C, | ||
6 | _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, | ||
7 | _C, _C, _C, _C, _C, _C, _C, _C, | ||
8 | _C, _C, _C, _C, _C, _C, _C, _C, | ||
9 | _S|_B, _P, _P, _P, _P, _P, _P, _P, | ||
10 | _P, _P, _P, _P, _P, _P, _P, _P, | ||
11 | _N, _N, _N, _N, _N, _N, _N, _N, | ||
12 | _N, _N, _P, _P, _P, _P, _P, _P, | ||
13 | _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, | ||
14 | _U, _U, _U, _U, _U, _U, _U, _U, | ||
15 | _U, _U, _U, _U, _U, _U, _U, _U, | ||
16 | _U, _U, _U, _P, _P, _P, _P, _P, | ||
17 | _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, | ||
18 | _L, _L, _L, _L, _L, _L, _L, _L, | ||
19 | _L, _L, _L, _L, _L, _L, _L, _L, | ||
20 | _L, _L, _L, _P, _P, _P, _P, _C | ||
21 | }; | ||
22 | |||
diff --git a/firmware/libc/errno.c b/firmware/libc/errno.c new file mode 100644 index 0000000000..6e7bb62b51 --- /dev/null +++ b/firmware/libc/errno.c | |||
@@ -0,0 +1 @@ | |||
int errno; | |||
diff --git a/firmware/libc/include/ctype.h b/firmware/libc/include/ctype.h new file mode 100644 index 0000000000..648e06dc5c --- /dev/null +++ b/firmware/libc/include/ctype.h | |||
@@ -0,0 +1,75 @@ | |||
1 | #ifndef _CTYPE_H_ | ||
2 | #ifdef __cplusplus | ||
3 | extern "C" { | ||
4 | #endif | ||
5 | #define _CTYPE_H_ | ||
6 | |||
7 | #include "_ansi.h" | ||
8 | |||
9 | int _EXFUN(isalnum, (int __c)); | ||
10 | int _EXFUN(isalpha, (int __c)); | ||
11 | int _EXFUN(iscntrl, (int __c)); | ||
12 | int _EXFUN(isdigit, (int __c)); | ||
13 | int _EXFUN(isgraph, (int __c)); | ||
14 | int _EXFUN(islower, (int __c)); | ||
15 | int _EXFUN(isprint, (int __c)); | ||
16 | int _EXFUN(ispunct, (int __c)); | ||
17 | int _EXFUN(isspace, (int __c)); | ||
18 | int _EXFUN(isupper, (int __c)); | ||
19 | int _EXFUN(isxdigit,(int __c)); | ||
20 | int _EXFUN(tolower, (int __c)); | ||
21 | int _EXFUN(toupper, (int __c)); | ||
22 | |||
23 | #ifndef __STRICT_ANSI__ | ||
24 | int _EXFUN(isascii, (int __c)); | ||
25 | int _EXFUN(toascii, (int __c)); | ||
26 | int _EXFUN(_tolower, (int __c)); | ||
27 | int _EXFUN(_toupper, (int __c)); | ||
28 | #endif | ||
29 | |||
30 | #define _U 01 | ||
31 | #define _L 02 | ||
32 | #define _N 04 | ||
33 | #define _S 010 | ||
34 | #define _P 020 | ||
35 | #define _C 040 | ||
36 | #define _X 0100 | ||
37 | #define _B 0200 | ||
38 | |||
39 | #ifdef PLUGIN | ||
40 | #define _ctype_ (rb->_rbctype_) | ||
41 | #else | ||
42 | extern const unsigned char _ctype_[257]; | ||
43 | #endif | ||
44 | |||
45 | #ifndef __cplusplus | ||
46 | #define isalpha(c) ((_ctype_+1)[(unsigned char)(c)]&(_U|_L)) | ||
47 | #define isupper(c) ((_ctype_+1)[(unsigned char)(c)]&_U) | ||
48 | #define islower(c) ((_ctype_+1)[(unsigned char)(c)]&_L) | ||
49 | #define isdigit(c) ((_ctype_+1)[(unsigned char)(c)]&_N) | ||
50 | #define isxdigit(c) ((_ctype_+1)[(unsigned char)(c)]&(_X|_N)) | ||
51 | #define isspace(c) ((_ctype_+1)[(unsigned char)(c)]&_S) | ||
52 | #define ispunct(c) ((_ctype_+1)[(unsigned char)(c)]&_P) | ||
53 | #define isalnum(c) ((_ctype_+1)[(unsigned char)(c)]&(_U|_L|_N)) | ||
54 | #define isprint(c) ((_ctype_+1)[(unsigned char)(c)]&(_P|_U|_L|_N|_B)) | ||
55 | #define isgraph(c) ((_ctype_+1)[(unsigned char)(c)]&(_P|_U|_L|_N)) | ||
56 | #define iscntrl(c) ((_ctype_+1)[(unsigned char)(c)]&_C) | ||
57 | /* Non-gcc versions will get the library versions, and will be | ||
58 | slightly slower */ | ||
59 | #ifdef __GNUC__ | ||
60 | # define toupper(c) \ | ||
61 | __extension__ ({ int __x = (unsigned char) (c); islower(__x) ? (__x - 'a' + 'A') : __x;}) | ||
62 | # define tolower(c) \ | ||
63 | __extension__ ({ int __x = (unsigned char) (c); isupper(__x) ? (__x - 'A' + 'a') : __x;}) | ||
64 | #endif | ||
65 | #endif /* !__cplusplus */ | ||
66 | |||
67 | #ifndef __STRICT_ANSI__ | ||
68 | #define isascii(c) ((unsigned char)(c)<=0177) | ||
69 | #define toascii(c) ((c)&0177) | ||
70 | #endif | ||
71 | |||
72 | #ifdef __cplusplus | ||
73 | } | ||
74 | #endif | ||
75 | #endif /* _CTYPE_H_ */ | ||
diff --git a/firmware/libc/include/errno.h b/firmware/libc/include/errno.h new file mode 100644 index 0000000000..6a24a1938f --- /dev/null +++ b/firmware/libc/include/errno.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* errno is not a global variable, because that would make using it | ||
2 | non-reentrant. Instead, its address is returned by the function | ||
3 | __errno. */ | ||
4 | |||
5 | #if (defined(SIMULATOR)||defined(__PCTOOL__)) && !defined(__MINGW32__) && !defined(__CYGWIN__) | ||
6 | |||
7 | #include "/usr/include/errno.h" /* use the host system implementation */ | ||
8 | |||
9 | #else /* use our own implementation */ | ||
10 | |||
11 | #ifndef _SYS_ERRNO_H_ | ||
12 | |||
13 | #ifdef PLUGIN | ||
14 | #define errno (*rb->__errno) | ||
15 | #else | ||
16 | extern int errno; | ||
17 | #endif | ||
18 | |||
19 | #define EPERM 1 /* Not super-user */ | ||
20 | #define ENOENT 2 /* No such file or directory */ | ||
21 | #define ESRCH 3 /* No such process */ | ||
22 | #define EINTR 4 /* Interrupted system call */ | ||
23 | #define EIO 5 /* I/O error */ | ||
24 | #define ENXIO 6 /* No such device or address */ | ||
25 | #define E2BIG 7 /* Arg list too long */ | ||
26 | #define ENOEXEC 8 /* Exec format error */ | ||
27 | #define EBADF 9 /* Bad file number */ | ||
28 | #define ECHILD 10 /* No children */ | ||
29 | #define EAGAIN 11 /* No more processes */ | ||
30 | #define ENOMEM 12 /* Not enough core */ | ||
31 | #define EACCES 13 /* Permission denied */ | ||
32 | #define EFAULT 14 /* Bad address */ | ||
33 | #define ENOTBLK 15 /* Block device required */ | ||
34 | #define EBUSY 16 /* Mount device busy */ | ||
35 | #define EEXIST 17 /* File exists */ | ||
36 | #define EXDEV 18 /* Cross-device link */ | ||
37 | #define ENODEV 19 /* No such device */ | ||
38 | #define ENOTDIR 20 /* Not a directory */ | ||
39 | #define EISDIR 21 /* Is a directory */ | ||
40 | #define EINVAL 22 /* Invalid argument */ | ||
41 | #define ENFILE 23 /* Too many open files in system */ | ||
42 | #define EMFILE 24 /* Too many open files */ | ||
43 | #define ENOTTY 25 /* Not a typewriter */ | ||
44 | #define ETXTBSY 26 /* Text file busy */ | ||
45 | #define EFBIG 27 /* File too large */ | ||
46 | #define ENOSPC 28 /* No space left on device */ | ||
47 | #define ESPIPE 29 /* Illegal seek */ | ||
48 | #define EROFS 30 /* Read only file system */ | ||
49 | #define EMLINK 31 /* Too many links */ | ||
50 | #define EPIPE 32 /* Broken pipe */ | ||
51 | #define EDOM 33 /* Math arg out of domain of func */ | ||
52 | #define ERANGE 34 /* Math result not representable */ | ||
53 | #define ENOMSG 35 /* No message of desired type */ | ||
54 | #define EIDRM 36 /* Identifier removed */ | ||
55 | #define ECHRNG 37 /* Channel number out of range */ | ||
56 | #define EL2NSYNC 38 /* Level 2 not synchronized */ | ||
57 | #define EL3HLT 39 /* Level 3 halted */ | ||
58 | #define EL3RST 40 /* Level 3 reset */ | ||
59 | #define ELNRNG 41 /* Link number out of range */ | ||
60 | #define EUNATCH 42 /* Protocol driver not attached */ | ||
61 | #define ENOCSI 43 /* No CSI structure available */ | ||
62 | #define EL2HLT 44 /* Level 2 halted */ | ||
63 | #define EDEADLK 45 /* Deadlock condition */ | ||
64 | #define ENOLCK 46 /* No record locks available */ | ||
65 | #define EBADE 50 /* Invalid exchange */ | ||
66 | #define EBADR 51 /* Invalid request descriptor */ | ||
67 | #define EXFULL 52 /* Exchange full */ | ||
68 | #define ENOANO 53 /* No anode */ | ||
69 | #define EBADRQC 54 /* Invalid request code */ | ||
70 | #define EBADSLT 55 /* Invalid slot */ | ||
71 | #define EDEADLOCK 56 /* File locking deadlock error */ | ||
72 | #define EBFONT 57 /* Bad font file fmt */ | ||
73 | #define ENOSTR 60 /* Device not a stream */ | ||
74 | #define ENODATA 61 /* No data (for no delay io) */ | ||
75 | #define ETIME 62 /* Timer expired */ | ||
76 | #define ENOSR 63 /* Out of streams resources */ | ||
77 | #define ENONET 64 /* Machine is not on the network */ | ||
78 | #define ENOPKG 65 /* Package not installed */ | ||
79 | #define EREMOTE 66 /* The object is remote */ | ||
80 | #define ENOLINK 67 /* The link has been severed */ | ||
81 | #define EADV 68 /* Advertise error */ | ||
82 | #define ESRMNT 69 /* Srmount error */ | ||
83 | #define ECOMM 70 /* Communication error on send */ | ||
84 | #define EPROTO 71 /* Protocol error */ | ||
85 | #define EMULTIHOP 74 /* Multihop attempted */ | ||
86 | #define ELBIN 75 /* Inode is remote (not really error) */ | ||
87 | #define EDOTDOT 76 /* Cross mount point (not really error) */ | ||
88 | #define EBADMSG 77 /* Trying to read unreadable message */ | ||
89 | #define ENOTUNIQ 80 /* Given log. name not unique */ | ||
90 | #define EBADFD 81 /* f.d. invalid for this operation */ | ||
91 | #define EREMCHG 82 /* Remote address changed */ | ||
92 | #define ELIBACC 83 /* Can't access a needed shared lib */ | ||
93 | #define ELIBBAD 84 /* Accessing a corrupted shared lib */ | ||
94 | #define ELIBSCN 85 /* .lib section in a.out corrupted */ | ||
95 | #define ELIBMAX 86 /* Attempting to link in too many libs */ | ||
96 | #define ELIBEXEC 87 /* Attempting to exec a shared library */ | ||
97 | #define ENOSYS 88 /* Function not implemented */ | ||
98 | #define ENMFILE 89 /* No more files */ | ||
99 | #define ENOTEMPTY 90 /* Directory not empty */ | ||
100 | #define ENAMETOOLONG 91 /* File or path name too long */ | ||
101 | #define ELOOP 92 /* Too many symbolic links */ | ||
102 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ | ||
103 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ | ||
104 | #define ECONNRESET 104 /* Connection reset by peer */ | ||
105 | #define ENOBUFS 105 /* No buffer space available */ | ||
106 | #define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ | ||
107 | #define EPROTOTYPE 107 /* Protocol wrong type for socket */ | ||
108 | #define ENOTSOCK 108 /* Socket operation on non-socket */ | ||
109 | #define ENOPROTOOPT 109 /* Protocol not available */ | ||
110 | #define ESHUTDOWN 110 /* Can't send after socket shutdown */ | ||
111 | #define ECONNREFUSED 111 /* Connection refused */ | ||
112 | #define EADDRINUSE 112 /* Address already in use */ | ||
113 | #define ECONNABORTED 113 /* Connection aborted */ | ||
114 | #define ENETUNREACH 114 /* Network is unreachable */ | ||
115 | #define ENETDOWN 115 /* Network interface is not configured */ | ||
116 | #define ETIMEDOUT 116 /* Connection timed out */ | ||
117 | #define EHOSTDOWN 117 /* Host is down */ | ||
118 | #define EHOSTUNREACH 118 /* Host is unreachable */ | ||
119 | #define EINPROGRESS 119 /* Connection already in progress */ | ||
120 | #define EALREADY 120 /* Socket already connected */ | ||
121 | #define EDESTADDRREQ 121 /* Destination address required */ | ||
122 | #define EMSGSIZE 122 /* Message too long */ | ||
123 | #define EPROTONOSUPPORT 123 /* Unknown protocol */ | ||
124 | #define ESOCKTNOSUPPORT 124 /* Socket type not supported */ | ||
125 | #define EADDRNOTAVAIL 125 /* Address not available */ | ||
126 | #define ENETRESET 126 | ||
127 | #define EISCONN 127 /* Socket is already connected */ | ||
128 | #define ENOTCONN 128 /* Socket is not connected */ | ||
129 | #define ETOOMANYREFS 129 | ||
130 | #define EPROCLIM 130 | ||
131 | #define EUSERS 131 | ||
132 | #define EDQUOT 132 | ||
133 | #define ESTALE 133 | ||
134 | #define ENOTSUP 134 /* Not supported */ | ||
135 | #define ENOMEDIUM 135 /* No medium (in tape drive) */ | ||
136 | #define ENOSHARE 136 /* No such host or network path */ | ||
137 | #define ECASECLASH 137 /* Filename exists with different case */ | ||
138 | |||
139 | /* From cygwin32. */ | ||
140 | #define EWOULDBLOCK EAGAIN /* Operation would block */ | ||
141 | |||
142 | #define __ELASTERROR 2000 /* Users can add values starting here */ | ||
143 | |||
144 | #endif /* _SYS_ERRNO_H */ | ||
145 | #endif /* !SIMULATOR */ | ||
diff --git a/firmware/libc/include/inttypes.h b/firmware/libc/include/inttypes.h new file mode 100644 index 0000000000..c03609c6d8 --- /dev/null +++ b/firmware/libc/include/inttypes.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Dave Chapman | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __INTTYPES_H__ | ||
23 | #define __INTTYPES_H__ | ||
24 | |||
25 | #include <stdint.h> | ||
26 | |||
27 | /* could possibly have (f)printf format specifies here */ | ||
28 | |||
29 | #endif /* __INTTYPES_H__ */ | ||
diff --git a/firmware/libc/include/stdint.h b/firmware/libc/include/stdint.h new file mode 100644 index 0000000000..93f234c0e8 --- /dev/null +++ b/firmware/libc/include/stdint.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Dave Chapman | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __STDINT_H__ | ||
23 | #define __STDINT_H__ | ||
24 | |||
25 | #include <limits.h> | ||
26 | |||
27 | /* 8 bit */ | ||
28 | #define INT8_MIN SCHAR_MIN | ||
29 | #define INT8_MAX SCHAR_MAX | ||
30 | #define UINT8_MAX UCHAR_MAX | ||
31 | #define int8_t signed char | ||
32 | #define uint8_t unsigned char | ||
33 | |||
34 | /* 16 bit */ | ||
35 | #if USHRT_MAX == 0xffff | ||
36 | |||
37 | #define INT16_MIN SHRT_MIN | ||
38 | #define INT16_MAX SHRT_MAX | ||
39 | #define UINT16_MAX USHRT_MAX | ||
40 | #define int16_t short | ||
41 | #define uint16_t unsigned short | ||
42 | |||
43 | #endif | ||
44 | |||
45 | /* 32 bit */ | ||
46 | #if ULONG_MAX == 0xfffffffful | ||
47 | |||
48 | #define INT32_MIN LONG_MIN | ||
49 | #define INT32_MAX LONG_MAX | ||
50 | #define UINT32_MAX ULONG_MAX | ||
51 | #define int32_t long | ||
52 | #define uint32_t unsigned long | ||
53 | |||
54 | #define INTPTR_MIN LONG_MIN | ||
55 | #define INTPTR_MAX LONG_MAX | ||
56 | #define UINTPTR_MAX ULONG_MAX | ||
57 | #define intptr_t long | ||
58 | #define uintptr_t unsigned long | ||
59 | |||
60 | #elif UINT_MAX == 0xffffffffu | ||
61 | |||
62 | #define INT32_MIN INT_MIN | ||
63 | #define INT32_MAX INT_MAX | ||
64 | #define UINT32_MAX UINT_MAX | ||
65 | #define int32_t int | ||
66 | #define uint32_t unsigned int | ||
67 | |||
68 | #endif | ||
69 | |||
70 | /* 64 bit */ | ||
71 | #ifndef LLONG_MIN | ||
72 | #define LLONG_MIN ((long long)9223372036854775808ull) | ||
73 | #endif | ||
74 | |||
75 | #ifndef LLONG_MAX | ||
76 | #define LLONG_MAX 9223372036854775807ll | ||
77 | #endif | ||
78 | |||
79 | #ifndef ULLONG_MAX | ||
80 | #define ULLONG_MAX 18446744073709551615ull | ||
81 | #endif | ||
82 | |||
83 | #if ULONG_MAX == 0xffffffffffffffffull | ||
84 | |||
85 | #define INT64_MIN LONG_MIN | ||
86 | #define INT64_MAX LONG_MAX | ||
87 | #define UINT64_MAX ULONG_MAX | ||
88 | #define int64_t long | ||
89 | #define uint64_t unsigned long | ||
90 | |||
91 | #define INTPTR_MIN LONG_MIN | ||
92 | #define INTPTR_MAX LONG_MAX | ||
93 | #define UINTPTR_MAX ULONG_MAX | ||
94 | #define intptr_t long | ||
95 | #define uintptr_t unsigned long | ||
96 | |||
97 | #else | ||
98 | |||
99 | #define INT64_MIN LLONG_MIN | ||
100 | #define INT64_MAX LLONG_MAX | ||
101 | #define UINT64_MAX ULLONG_MAX | ||
102 | #define int64_t long long | ||
103 | #define uint64_t unsigned long long | ||
104 | |||
105 | #endif | ||
106 | |||
107 | #endif /* __STDINT_H__ */ | ||
diff --git a/firmware/libc/include/stdio.h b/firmware/libc/include/stdio.h new file mode 100644 index 0000000000..d9a6dce55f --- /dev/null +++ b/firmware/libc/include/stdio.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef _STDIO_H_ | ||
2 | #define _STDIO_H_ | ||
3 | |||
4 | #include <_ansi.h> | ||
5 | |||
6 | #define __need_size_t | ||
7 | #include <stddef.h> | ||
8 | |||
9 | #define __need___va_list | ||
10 | #include <stdarg.h> | ||
11 | |||
12 | #ifndef NULL | ||
13 | #define NULL 0 | ||
14 | #endif | ||
15 | |||
16 | #define EOF (-1) | ||
17 | |||
18 | #ifndef SEEK_SET | ||
19 | #define SEEK_SET 0 /* set file offset to offset */ | ||
20 | #endif | ||
21 | #ifndef SEEK_CUR | ||
22 | #define SEEK_CUR 1 /* set file offset to current plus offset */ | ||
23 | #endif | ||
24 | #ifndef SEEK_END | ||
25 | #define SEEK_END 2 /* set file offset to EOF plus offset */ | ||
26 | #endif | ||
27 | |||
28 | #define TMP_MAX 26 | ||
29 | |||
30 | #ifdef __GNUC__ | ||
31 | #define __VALIST __gnuc_va_list | ||
32 | #else | ||
33 | #define __VALIST char* | ||
34 | #endif | ||
35 | |||
36 | int vsnprintf (char *buf, size_t size, const char *fmt, __VALIST ap); | ||
37 | |||
38 | int sprintf (char *buf, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); | ||
39 | |||
40 | int snprintf (char *buf, size_t size, const char *fmt, ...) | ||
41 | ATTRIBUTE_PRINTF(3, 4); | ||
42 | |||
43 | /* callback function is called for every output character (byte) with userp and | ||
44 | * should return 0 when ch is a char other than '\0' that should stop printing */ | ||
45 | int vuprintf(int (*push)(void *userp, unsigned char data), | ||
46 | void *userp, const char *fmt, __VALIST ap); | ||
47 | |||
48 | int sscanf(const char *s, const char *fmt, ...) | ||
49 | ATTRIBUTE_SCANF(2, 3); | ||
50 | |||
51 | #ifdef SIMULATOR | ||
52 | typedef void FILE; | ||
53 | int vfprintf(FILE *stream, const char *format, __VALIST ap); | ||
54 | #ifdef WIN32 | ||
55 | #define FILENAME_MAX 260 /* ugly hard-coded value of a limit that is set | ||
56 | in file.h */ | ||
57 | #endif | ||
58 | #endif | ||
59 | |||
60 | #endif /* _STDIO_H_ */ | ||
diff --git a/firmware/libc/include/stdlib.h b/firmware/libc/include/stdlib.h new file mode 100644 index 0000000000..5f6db6da8a --- /dev/null +++ b/firmware/libc/include/stdlib.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * stdlib.h | ||
3 | * | ||
4 | * Definitions for common types, variables, and functions. | ||
5 | */ | ||
6 | |||
7 | #ifndef _STDLIB_H_ | ||
8 | #ifdef __cplusplus | ||
9 | extern "C" { | ||
10 | #endif | ||
11 | #define _STDLIB_H_ | ||
12 | |||
13 | #include "_ansi.h" | ||
14 | |||
15 | #define __need_size_t | ||
16 | #define __need_wchar_t | ||
17 | #include <stddef.h> | ||
18 | |||
19 | #ifndef NULL | ||
20 | #define NULL ((void*)0) | ||
21 | #endif | ||
22 | |||
23 | #define EXIT_FAILURE 1 | ||
24 | #define EXIT_SUCCESS 0 | ||
25 | |||
26 | _VOID _EXFUN(qsort,(_PTR __base, size_t __nmemb, size_t __size, int(*_compar)(const _PTR, const _PTR))); | ||
27 | |||
28 | void *malloc(size_t); | ||
29 | void *calloc (size_t nmemb, size_t size); | ||
30 | void free(void *); | ||
31 | void *realloc(void *, size_t); | ||
32 | |||
33 | #define RAND_MAX INT_MAX | ||
34 | |||
35 | void srand(unsigned int seed); | ||
36 | int rand(void); | ||
37 | |||
38 | #ifndef ABS | ||
39 | #if defined(__GNUC__) | ||
40 | #define ABS(a) ({typeof (a) ___a = (a); ___a < 0 ? -___a: ___a; }) | ||
41 | #else | ||
42 | #define ABS(a) (((a) < 0) ? -(a) : (a)) | ||
43 | #endif /* __GNUC__ */ | ||
44 | #endif | ||
45 | |||
46 | #define abs(x) ((int)ABS(x)) | ||
47 | #define labs(x) ((long)abs(x)) | ||
48 | |||
49 | #ifdef SIMULATOR | ||
50 | void exit(int status); | ||
51 | #endif | ||
52 | |||
53 | int atoi (const char *str); | ||
54 | |||
55 | #ifdef __cplusplus | ||
56 | } | ||
57 | #endif | ||
58 | #endif /* _STDLIB_H_ */ | ||
diff --git a/firmware/libc/include/string.h b/firmware/libc/include/string.h new file mode 100644 index 0000000000..8986bd6a0c --- /dev/null +++ b/firmware/libc/include/string.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * string.h | ||
3 | * | ||
4 | * Definitions for memory and string functions. | ||
5 | */ | ||
6 | |||
7 | #ifndef _STRING_H_ | ||
8 | #define _STRING_H_ | ||
9 | |||
10 | #ifdef __cplusplus | ||
11 | extern "C" { | ||
12 | #endif | ||
13 | |||
14 | #include "_ansi.h" | ||
15 | |||
16 | #include <stddef.h> | ||
17 | |||
18 | #if !defined(__size_t_defined)&& !defined(_SIZE_T_) && !defined(size_t) && !defined(_SIZE_T_DECLARED) | ||
19 | #define __size_t_defined | ||
20 | #define _SIZE_T | ||
21 | #define _SIZE_T_ | ||
22 | #define _SIZE_T_DECLARED | ||
23 | #define size_t size_t | ||
24 | typedef unsigned long size_t; | ||
25 | #endif | ||
26 | |||
27 | #ifndef NULL | ||
28 | #define NULL ((void*)0) | ||
29 | #endif | ||
30 | |||
31 | _PTR _EXFUN(memchr,(const _PTR, int, size_t)); | ||
32 | int _EXFUN(memcmp,(const _PTR, const _PTR, size_t)); | ||
33 | _PTR _EXFUN(memcpy,(_PTR, const _PTR, size_t)); | ||
34 | _PTR _EXFUN(memmove,(_PTR, const _PTR, size_t)); | ||
35 | _PTR _EXFUN(memset,(_PTR, int, size_t)); | ||
36 | char *_EXFUN(strcat,(char *, const char *)); | ||
37 | char *_EXFUN(strchr,(const char *, int)); | ||
38 | int _EXFUN(strcmp,(const char *, const char *)); | ||
39 | int _EXFUN(strcoll,(const char *, const char *)); | ||
40 | char *_EXFUN(strcpy,(char *, const char *)); | ||
41 | size_t _EXFUN(strcspn,(const char *, const char *)); | ||
42 | char *_EXFUN(strerror,(int)); | ||
43 | size_t _EXFUN(strlen,(const char *)); | ||
44 | char *_EXFUN(strncat,(char *, const char *, size_t)); | ||
45 | int _EXFUN(strncmp,(const char *, const char *, size_t)); | ||
46 | char *_EXFUN(strpbrk,(const char *, const char *)); | ||
47 | char *_EXFUN(strrchr,(const char *, int)); | ||
48 | size_t _EXFUN(strspn,(const char *, const char *)); | ||
49 | char *_EXFUN(strstr,(const char *, const char *)); | ||
50 | char *_EXFUN(strcasestr,(const char *, const char *)); | ||
51 | |||
52 | size_t strlcpy(char *dst, const char *src, size_t siz); | ||
53 | size_t strlcat(char *dst, const char *src, size_t siz); | ||
54 | |||
55 | #ifndef _REENT_ONLY | ||
56 | char *_EXFUN(strtok,(char *, const char *)); | ||
57 | #endif | ||
58 | |||
59 | size_t _EXFUN(strxfrm,(char *, const char *, size_t)); | ||
60 | |||
61 | #ifndef __STRICT_ANSI__ | ||
62 | char *_EXFUN(strtok_r,(char *, const char *, char **)); | ||
63 | |||
64 | _PTR _EXFUN(memccpy,(_PTR, const _PTR, int, size_t)); | ||
65 | int _EXFUN(strcasecmp,(const char *, const char *)); | ||
66 | int _EXFUN(strncasecmp,(const char *, const char *, size_t)); | ||
67 | |||
68 | #ifdef __CYGWIN__ | ||
69 | #ifndef DEFS_H /* Kludge to work around problem compiling in gdb */ | ||
70 | const char *_EXFUN(strsignal, (int __signo)); | ||
71 | #endif | ||
72 | int _EXFUN(strtosigno, (const char *__name)); | ||
73 | #endif | ||
74 | |||
75 | /* These function names are used on Windows and perhaps other systems. */ | ||
76 | #ifndef strcmpi | ||
77 | #define strcmpi strcasecmp | ||
78 | #endif | ||
79 | #ifndef stricmp | ||
80 | #define stricmp strcasecmp | ||
81 | #endif | ||
82 | #ifndef strncmpi | ||
83 | #define strncmpi strncasecmp | ||
84 | #endif | ||
85 | #ifndef strnicmp | ||
86 | #define strnicmp strncasecmp | ||
87 | #endif | ||
88 | |||
89 | #endif /* ! __STRICT_ANSI__ */ | ||
90 | |||
91 | #ifdef __cplusplus | ||
92 | } | ||
93 | #endif | ||
94 | #endif /* _STRING_H_ */ | ||
diff --git a/firmware/libc/include/time.h b/firmware/libc/include/time.h new file mode 100644 index 0000000000..912fafe7ca --- /dev/null +++ b/firmware/libc/include/time.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * time.h | ||
3 | * | ||
4 | * Struct declaration for dealing with time. | ||
5 | */ | ||
6 | |||
7 | #ifndef _TIME_H_ | ||
8 | #define _TIME_H_ | ||
9 | |||
10 | #ifdef WPSEDITOR | ||
11 | #include "inttypes.h" | ||
12 | #include <time.h> | ||
13 | #endif | ||
14 | |||
15 | struct tm | ||
16 | { | ||
17 | int tm_sec; | ||
18 | int tm_min; | ||
19 | int tm_hour; | ||
20 | int tm_mday; | ||
21 | int tm_mon; | ||
22 | int tm_year; | ||
23 | int tm_wday; | ||
24 | int tm_yday; | ||
25 | int tm_isdst; | ||
26 | }; | ||
27 | |||
28 | #if !defined(_TIME_T_DEFINED) && !defined(_TIME_T_DECLARED) | ||
29 | typedef long time_t; | ||
30 | |||
31 | /* this define below is used by the mingw headers to prevent duplicate | ||
32 | typedefs */ | ||
33 | #define _TIME_T_DEFINED | ||
34 | #define _TIME_T_DECLARED | ||
35 | time_t time(time_t *t); | ||
36 | struct tm *localtime(const time_t *timep); | ||
37 | time_t mktime(struct tm *t); | ||
38 | |||
39 | #endif /* SIMULATOR */ | ||
40 | |||
41 | #ifdef __PCTOOL__ | ||
42 | /* this time.h does not define struct timespec, | ||
43 | so tell sys/stat.h not to use it */ | ||
44 | #undef __USE_MISC | ||
45 | #endif | ||
46 | |||
47 | #endif /* _TIME_H_ */ | ||
48 | |||
49 | |||
diff --git a/firmware/libc/memchr.c b/firmware/libc/memchr.c new file mode 100644 index 0000000000..26bdb9eea3 --- /dev/null +++ b/firmware/libc/memchr.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<memchr>>---search for character in memory | ||
4 | |||
5 | INDEX | ||
6 | memchr | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | void * memchr(const void *<[s1]>, int <[c]>, size_t <[n]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | void * memchr(<[s1]>, <[c]>, <[n]>); | ||
15 | void *<[string]>; | ||
16 | int *<[c]>; | ||
17 | size_t *<[n]>; | ||
18 | |||
19 | DESCRIPTION | ||
20 | This function scans the first <[n]> bytes of the memory pointed | ||
21 | to by <[s1]> for the character <[c]> (converted to a char). | ||
22 | |||
23 | RETURNS | ||
24 | Returns a pointer to the matching byte, or a null pointer if | ||
25 | <[c]> does not occur in <[s1]>. | ||
26 | |||
27 | PORTABILITY | ||
28 | <<memchr>> is ANSI C. | ||
29 | |||
30 | <<memchr>> requires no supporting OS subroutines. | ||
31 | |||
32 | QUICKREF | ||
33 | memchr ansi pure | ||
34 | */ | ||
35 | |||
36 | #include <string.h> | ||
37 | #include <limits.h> | ||
38 | |||
39 | /* Nonzero if X is not aligned on a "long" boundary. */ | ||
40 | #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) | ||
41 | |||
42 | /* How many bytes are loaded each iteration of the word copy loop. */ | ||
43 | #define LBLOCKSIZE (sizeof (long)) | ||
44 | |||
45 | #if LONG_MAX == 2147483647L | ||
46 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
47 | #else | ||
48 | #if LONG_MAX == 9223372036854775807L | ||
49 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
50 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
51 | #else | ||
52 | #error long int is not a 32bit or 64bit type. | ||
53 | #endif | ||
54 | #endif | ||
55 | |||
56 | /* DETECTCHAR returns nonzero if (long)X contains the byte used | ||
57 | to fill (long)MASK. */ | ||
58 | #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) | ||
59 | |||
60 | void * | ||
61 | _DEFUN (memchr, (s1, i, n), | ||
62 | _CONST void *s1 _AND | ||
63 | int i _AND size_t n) | ||
64 | { | ||
65 | _CONST unsigned char *s = (_CONST unsigned char *)s1; | ||
66 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
67 | unsigned char c = (unsigned char)i; | ||
68 | |||
69 | while (n-- > 0) | ||
70 | { | ||
71 | if (*s == c) | ||
72 | { | ||
73 | return (void *)s; | ||
74 | } | ||
75 | s++; | ||
76 | } | ||
77 | |||
78 | return NULL; | ||
79 | #else | ||
80 | unsigned char c = (unsigned char)i; | ||
81 | unsigned long mask,j; | ||
82 | unsigned long *aligned_addr; | ||
83 | |||
84 | if (!UNALIGNED (s)) | ||
85 | { | ||
86 | mask = 0; | ||
87 | for (j = 0; j < LBLOCKSIZE; j++) | ||
88 | mask = (mask << 8) | c; | ||
89 | |||
90 | aligned_addr = (unsigned long*)s; | ||
91 | while ((!DETECTCHAR (*aligned_addr, mask)) && (n>LBLOCKSIZE)) | ||
92 | { | ||
93 | aligned_addr++; | ||
94 | n -= LBLOCKSIZE; | ||
95 | } | ||
96 | |||
97 | /* The block of bytes currently pointed to by aligned_addr | ||
98 | may contain the target character or there may be less than | ||
99 | LBLOCKSIZE bytes left to search. We check the last few | ||
100 | bytes using the bytewise search. */ | ||
101 | |||
102 | s = (unsigned char*)aligned_addr; | ||
103 | } | ||
104 | |||
105 | while (n-- > 0) | ||
106 | { | ||
107 | if (*s == c) | ||
108 | { | ||
109 | return (void *)s; | ||
110 | } | ||
111 | s++; | ||
112 | } | ||
113 | |||
114 | return NULL; | ||
115 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
116 | } | ||
diff --git a/firmware/libc/memcmp.c b/firmware/libc/memcmp.c new file mode 100644 index 0000000000..1535fcf5b5 --- /dev/null +++ b/firmware/libc/memcmp.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<memcmp>>---compare two memory areas | ||
4 | |||
5 | INDEX | ||
6 | memcmp | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | int memcmp(<[s1]>, <[s2]>, <[n]>) | ||
15 | void *<[s1]>; | ||
16 | void *<[s2]>; | ||
17 | size_t <[n]>; | ||
18 | |||
19 | DESCRIPTION | ||
20 | This function compares not more than <[n]> characters of the | ||
21 | object pointed to by <[s1]> with the object pointed to by <[s2]>. | ||
22 | |||
23 | |||
24 | RETURNS | ||
25 | The function returns an integer greater than, equal to or | ||
26 | less than zero according to whether the object pointed to by | ||
27 | <[s1]> is greater than, equal to or less than the object | ||
28 | pointed to by <[s2]>. | ||
29 | |||
30 | PORTABILITY | ||
31 | <<memcmp>> is ANSI C. | ||
32 | |||
33 | <<memcmp>> requires no supporting OS subroutines. | ||
34 | |||
35 | QUICKREF | ||
36 | memcmp ansi pure | ||
37 | */ | ||
38 | |||
39 | #include <string.h> | ||
40 | |||
41 | |||
42 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
43 | #define UNALIGNED(X, Y) \ | ||
44 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
45 | |||
46 | /* How many bytes are copied each iteration of the word copy loop. */ | ||
47 | #define LBLOCKSIZE (sizeof (long)) | ||
48 | |||
49 | /* Threshhold for punting to the byte copier. */ | ||
50 | #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) | ||
51 | |||
52 | int | ||
53 | _DEFUN (memcmp, (m1, m2, n), | ||
54 | _CONST _PTR m1 _AND | ||
55 | _CONST _PTR m2 _AND | ||
56 | size_t n) | ||
57 | { | ||
58 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
59 | unsigned char *s1 = (unsigned char *) m1; | ||
60 | unsigned char *s2 = (unsigned char *) m2; | ||
61 | |||
62 | while (n--) | ||
63 | { | ||
64 | if (*s1 != *s2) | ||
65 | { | ||
66 | return *s1 - *s2; | ||
67 | } | ||
68 | s1++; | ||
69 | s2++; | ||
70 | } | ||
71 | return 0; | ||
72 | #else | ||
73 | unsigned char *s1 = (unsigned char *) m1; | ||
74 | unsigned char *s2 = (unsigned char *) m2; | ||
75 | unsigned long *a1; | ||
76 | unsigned long *a2; | ||
77 | |||
78 | /* If the size is too small, or either pointer is unaligned, | ||
79 | then we punt to the byte compare loop. Hopefully this will | ||
80 | not turn up in inner loops. */ | ||
81 | if (!TOO_SMALL(n) && !UNALIGNED(s1,s2)) | ||
82 | { | ||
83 | /* Otherwise, load and compare the blocks of memory one | ||
84 | word at a time. */ | ||
85 | a1 = (unsigned long*) s1; | ||
86 | a2 = (unsigned long*) s2; | ||
87 | while (n >= LBLOCKSIZE) | ||
88 | { | ||
89 | if (*a1 != *a2) | ||
90 | break; | ||
91 | a1++; | ||
92 | a2++; | ||
93 | n -= LBLOCKSIZE; | ||
94 | } | ||
95 | |||
96 | /* check m mod LBLOCKSIZE remaining characters */ | ||
97 | |||
98 | s1 = (unsigned char*)a1; | ||
99 | s2 = (unsigned char*)a2; | ||
100 | } | ||
101 | |||
102 | while (n--) | ||
103 | { | ||
104 | if (*s1 != *s2) | ||
105 | return *s1 - *s2; | ||
106 | s1++; | ||
107 | s2++; | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
112 | } | ||
113 | |||
diff --git a/firmware/libc/memcpy.c b/firmware/libc/memcpy.c new file mode 100644 index 0000000000..a89ac3c557 --- /dev/null +++ b/firmware/libc/memcpy.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<memcpy>>---copy memory regions | ||
4 | |||
5 | ANSI_SYNOPSIS | ||
6 | #include <string.h> | ||
7 | void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); | ||
8 | |||
9 | TRAD_SYNOPSIS | ||
10 | void *memcpy(<[out]>, <[in]>, <[n]> | ||
11 | void *<[out]>; | ||
12 | void *<[in]>; | ||
13 | size_t <[n]>; | ||
14 | |||
15 | DESCRIPTION | ||
16 | This function copies <[n]> bytes from the memory region | ||
17 | pointed to by <[in]> to the memory region pointed to by | ||
18 | <[out]>. | ||
19 | |||
20 | If the regions overlap, the behavior is undefined. | ||
21 | |||
22 | RETURNS | ||
23 | <<memcpy>> returns a pointer to the first byte of the <[out]> | ||
24 | region. | ||
25 | |||
26 | PORTABILITY | ||
27 | <<memcpy>> is ANSI C. | ||
28 | |||
29 | <<memcpy>> requires no supporting OS subroutines. | ||
30 | |||
31 | QUICKREF | ||
32 | memcpy ansi pure | ||
33 | */ | ||
34 | |||
35 | #include "config.h" | ||
36 | #include <_ansi.h> | ||
37 | #include <string.h> | ||
38 | |||
39 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
40 | #define UNALIGNED(X, Y) \ | ||
41 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
42 | |||
43 | /* How many bytes are copied each iteration of the 4X unrolled loop. */ | ||
44 | #define BIGBLOCKSIZE (sizeof (long) << 2) | ||
45 | |||
46 | /* How many bytes are copied each iteration of the word copy loop. */ | ||
47 | #define LITTLEBLOCKSIZE (sizeof (long)) | ||
48 | |||
49 | /* Threshold for punting to the byte copier. */ | ||
50 | #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) | ||
51 | |||
52 | _PTR | ||
53 | _DEFUN (memcpy, (dst0, src0, len0), | ||
54 | _PTR dst0 _AND | ||
55 | _CONST _PTR src0 _AND | ||
56 | size_t len0) ICODE_ATTR; | ||
57 | |||
58 | _PTR | ||
59 | _DEFUN (memcpy, (dst0, src0, len0), | ||
60 | _PTR dst0 _AND | ||
61 | _CONST _PTR src0 _AND | ||
62 | size_t len0) | ||
63 | { | ||
64 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
65 | char *dst = (char *) dst0; | ||
66 | char *src = (char *) src0; | ||
67 | |||
68 | _PTR save = dst0; | ||
69 | |||
70 | while (len0--) | ||
71 | { | ||
72 | *dst++ = *src++; | ||
73 | } | ||
74 | |||
75 | return save; | ||
76 | #else | ||
77 | char *dst = dst0; | ||
78 | _CONST char *src = src0; | ||
79 | long *aligned_dst; | ||
80 | _CONST long *aligned_src; | ||
81 | unsigned int len = len0; | ||
82 | |||
83 | /* If the size is small, or either SRC or DST is unaligned, | ||
84 | then punt into the byte copy loop. This should be rare. */ | ||
85 | if (!TOO_SMALL(len) && !UNALIGNED (src, dst)) | ||
86 | { | ||
87 | aligned_dst = (long*)dst; | ||
88 | aligned_src = (long*)src; | ||
89 | |||
90 | /* Copy 4X long words at a time if possible. */ | ||
91 | while (len >= BIGBLOCKSIZE) | ||
92 | { | ||
93 | *aligned_dst++ = *aligned_src++; | ||
94 | *aligned_dst++ = *aligned_src++; | ||
95 | *aligned_dst++ = *aligned_src++; | ||
96 | *aligned_dst++ = *aligned_src++; | ||
97 | len -= (unsigned int)BIGBLOCKSIZE; | ||
98 | } | ||
99 | |||
100 | /* Copy one long word at a time if possible. */ | ||
101 | while (len >= LITTLEBLOCKSIZE) | ||
102 | { | ||
103 | *aligned_dst++ = *aligned_src++; | ||
104 | len -= LITTLEBLOCKSIZE; | ||
105 | } | ||
106 | |||
107 | /* Pick up any residual with a byte copier. */ | ||
108 | dst = (char*)aligned_dst; | ||
109 | src = (char*)aligned_src; | ||
110 | } | ||
111 | |||
112 | while (len--) | ||
113 | *dst++ = *src++; | ||
114 | |||
115 | return dst0; | ||
116 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
117 | } | ||
diff --git a/firmware/libc/memmove.c b/firmware/libc/memmove.c new file mode 100644 index 0000000000..5f423964bb --- /dev/null +++ b/firmware/libc/memmove.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<memmove>>---move possibly overlapping memory | ||
4 | |||
5 | INDEX | ||
6 | memmove | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | void *memmove(<[dst]>, <[src]>, <[length]>) | ||
15 | void *<[dst]>; | ||
16 | void *<[src]>; | ||
17 | size_t <[length]>; | ||
18 | |||
19 | DESCRIPTION | ||
20 | This function moves <[length]> characters from the block of | ||
21 | memory starting at <<*<[src]>>> to the memory starting at | ||
22 | <<*<[dst]>>>. <<memmove>> reproduces the characters correctly | ||
23 | at <<*<[dst]>>> even if the two areas overlap. | ||
24 | |||
25 | |||
26 | RETURNS | ||
27 | The function returns <[dst]> as passed. | ||
28 | |||
29 | PORTABILITY | ||
30 | <<memmove>> is ANSI C. | ||
31 | |||
32 | <<memmove>> requires no supporting OS subroutines. | ||
33 | |||
34 | QUICKREF | ||
35 | memmove ansi pure | ||
36 | */ | ||
37 | |||
38 | #include "config.h" | ||
39 | #include <_ansi.h> | ||
40 | #include <string.h> | ||
41 | |||
42 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
43 | #define UNALIGNED(X, Y) \ | ||
44 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
45 | |||
46 | /* How many bytes are copied each iteration of the 4X unrolled loop. */ | ||
47 | #define BIGBLOCKSIZE (sizeof (long) << 2) | ||
48 | |||
49 | /* How many bytes are copied each iteration of the word copy loop. */ | ||
50 | #define LITTLEBLOCKSIZE (sizeof (long)) | ||
51 | |||
52 | /* Threshhold for punting to the byte copier. */ | ||
53 | #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) | ||
54 | |||
55 | _PTR | ||
56 | _DEFUN (memmove, (dst_void, src_void, length), | ||
57 | _PTR dst_void _AND | ||
58 | _CONST _PTR src_void _AND | ||
59 | size_t length) ICODE_ATTR; | ||
60 | |||
61 | _PTR | ||
62 | _DEFUN (memmove, (dst_void, src_void, length), | ||
63 | _PTR dst_void _AND | ||
64 | _CONST _PTR src_void _AND | ||
65 | size_t length) | ||
66 | { | ||
67 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
68 | char *dst = dst_void; | ||
69 | _CONST char *src = src_void; | ||
70 | |||
71 | if (src < dst && dst < src + length) | ||
72 | { | ||
73 | /* Have to copy backwards */ | ||
74 | src += length; | ||
75 | dst += length; | ||
76 | while (length--) | ||
77 | { | ||
78 | *--dst = *--src; | ||
79 | } | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | while (length--) | ||
84 | { | ||
85 | *dst++ = *src++; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | return dst_void; | ||
90 | #else | ||
91 | char *dst = dst_void; | ||
92 | _CONST char *src = src_void; | ||
93 | long *aligned_dst; | ||
94 | _CONST long *aligned_src; | ||
95 | unsigned int len = length; | ||
96 | |||
97 | if (src < dst && dst < src + len) | ||
98 | { | ||
99 | /* Destructive overlap...have to copy backwards */ | ||
100 | src += len; | ||
101 | dst += len; | ||
102 | while (len--) | ||
103 | { | ||
104 | *--dst = *--src; | ||
105 | } | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | /* Use optimizing algorithm for a non-destructive copy to closely | ||
110 | match memcpy. If the size is small or either SRC or DST is unaligned, | ||
111 | then punt into the byte copy loop. This should be rare. */ | ||
112 | if (!TOO_SMALL(len) && !UNALIGNED (src, dst)) | ||
113 | { | ||
114 | aligned_dst = (long*)dst; | ||
115 | aligned_src = (long*)src; | ||
116 | |||
117 | /* Copy 4X long words at a time if possible. */ | ||
118 | while (len >= BIGBLOCKSIZE) | ||
119 | { | ||
120 | *aligned_dst++ = *aligned_src++; | ||
121 | *aligned_dst++ = *aligned_src++; | ||
122 | *aligned_dst++ = *aligned_src++; | ||
123 | *aligned_dst++ = *aligned_src++; | ||
124 | len -= BIGBLOCKSIZE; | ||
125 | } | ||
126 | |||
127 | /* Copy one long word at a time if possible. */ | ||
128 | while (len >= LITTLEBLOCKSIZE) | ||
129 | { | ||
130 | *aligned_dst++ = *aligned_src++; | ||
131 | len -= LITTLEBLOCKSIZE; | ||
132 | } | ||
133 | |||
134 | /* Pick up any residual with a byte copier. */ | ||
135 | dst = (char*)aligned_dst; | ||
136 | src = (char*)aligned_src; | ||
137 | } | ||
138 | |||
139 | while (len--) | ||
140 | { | ||
141 | *dst++ = *src++; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | return dst_void; | ||
146 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
147 | } | ||
diff --git a/firmware/libc/memset.c b/firmware/libc/memset.c new file mode 100644 index 0000000000..7b8d2137e8 --- /dev/null +++ b/firmware/libc/memset.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<memset>>---set an area of memory | ||
4 | |||
5 | INDEX | ||
6 | memset | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | void *memset(const void *<[dst]>, int <[c]>, size_t <[length]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | void *memset(<[dst]>, <[c]>, <[length]>) | ||
15 | void *<[dst]>; | ||
16 | int <[c]>; | ||
17 | size_t <[length]>; | ||
18 | |||
19 | DESCRIPTION | ||
20 | This function converts the argument <[c]> into an unsigned | ||
21 | char and fills the first <[length]> characters of the array | ||
22 | pointed to by <[dst]> to the value. | ||
23 | |||
24 | RETURNS | ||
25 | <<memset>> returns the value of <[m]>. | ||
26 | |||
27 | PORTABILITY | ||
28 | <<memset>> is ANSI C. | ||
29 | |||
30 | <<memset>> requires no supporting OS subroutines. | ||
31 | |||
32 | QUICKREF | ||
33 | memset ansi pure | ||
34 | */ | ||
35 | |||
36 | #include <string.h> | ||
37 | #include "_ansi.h" | ||
38 | |||
39 | #define LBLOCKSIZE (sizeof(long)) | ||
40 | #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) | ||
41 | #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) | ||
42 | |||
43 | _PTR | ||
44 | _DEFUN (memset, (m, c, n), | ||
45 | _PTR m _AND | ||
46 | int c _AND | ||
47 | size_t n) | ||
48 | { | ||
49 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
50 | char *s = (char *) m; | ||
51 | |||
52 | while (n-- != 0) | ||
53 | { | ||
54 | *s++ = (char) c; | ||
55 | } | ||
56 | |||
57 | return m; | ||
58 | #else | ||
59 | char *s = (char *) m; | ||
60 | unsigned int i; | ||
61 | unsigned long buffer; | ||
62 | unsigned long *aligned_addr; | ||
63 | |||
64 | if (!TOO_SMALL (n) && !UNALIGNED (m)) | ||
65 | { | ||
66 | /* If we get this far, we know that n is large and m is word-aligned. */ | ||
67 | |||
68 | aligned_addr = (unsigned long*)m; | ||
69 | |||
70 | /* Store C into each char sized location in BUFFER so that | ||
71 | we can set large blocks quickly. */ | ||
72 | c &= 0xff; | ||
73 | if (LBLOCKSIZE == 4) | ||
74 | { | ||
75 | buffer = (c << 8) | c; | ||
76 | buffer |= (buffer << 16); | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | buffer = 0; | ||
81 | for (i = 0; i < LBLOCKSIZE; i++) | ||
82 | buffer = (buffer << 8) | c; | ||
83 | } | ||
84 | |||
85 | while (n >= LBLOCKSIZE*4) | ||
86 | { | ||
87 | *aligned_addr++ = buffer; | ||
88 | *aligned_addr++ = buffer; | ||
89 | *aligned_addr++ = buffer; | ||
90 | *aligned_addr++ = buffer; | ||
91 | n -= 4*LBLOCKSIZE; | ||
92 | } | ||
93 | |||
94 | while (n >= LBLOCKSIZE) | ||
95 | { | ||
96 | *aligned_addr++ = buffer; | ||
97 | n -= LBLOCKSIZE; | ||
98 | } | ||
99 | /* Pick up the remainder with a bytewise loop. */ | ||
100 | s = (char*)aligned_addr; | ||
101 | } | ||
102 | |||
103 | while (n--) | ||
104 | { | ||
105 | *s++ = (char)c; | ||
106 | } | ||
107 | |||
108 | return m; | ||
109 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
110 | } | ||
diff --git a/firmware/libc/mktime.c b/firmware/libc/mktime.c new file mode 100644 index 0000000000..a52381ede5 --- /dev/null +++ b/firmware/libc/mktime.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Linus Nielsen Feltzing | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #include <time.h> | ||
24 | #include "config.h" | ||
25 | |||
26 | #if CONFIG_RTC | ||
27 | /* mktime() code taken from lynx-2.8.5 source, written | ||
28 | by Philippe De Muyter <phdm@macqel.be> */ | ||
29 | time_t mktime(struct tm *t) | ||
30 | { | ||
31 | short month, year; | ||
32 | time_t result; | ||
33 | static int m_to_d[12] = | ||
34 | {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; | ||
35 | |||
36 | month = t->tm_mon; | ||
37 | year = t->tm_year + month / 12 + 1900; | ||
38 | month %= 12; | ||
39 | if (month < 0) | ||
40 | { | ||
41 | year -= 1; | ||
42 | month += 12; | ||
43 | } | ||
44 | result = (year - 1970) * 365 + (year - 1969) / 4 + m_to_d[month]; | ||
45 | result = (year - 1970) * 365 + m_to_d[month]; | ||
46 | if (month <= 1) | ||
47 | year -= 1; | ||
48 | result += (year - 1968) / 4; | ||
49 | result -= (year - 1900) / 100; | ||
50 | result += (year - 1600) / 400; | ||
51 | result += t->tm_mday; | ||
52 | result -= 1; | ||
53 | result *= 24; | ||
54 | result += t->tm_hour; | ||
55 | result *= 60; | ||
56 | result += t->tm_min; | ||
57 | result *= 60; | ||
58 | result += t->tm_sec; | ||
59 | return(result); | ||
60 | } | ||
61 | #endif | ||
diff --git a/firmware/libc/qsort.c b/firmware/libc/qsort.c new file mode 100644 index 0000000000..8c4d1ad511 --- /dev/null +++ b/firmware/libc/qsort.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<qsort>>---sort an array | ||
4 | |||
5 | INDEX | ||
6 | qsort | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <stdlib.h> | ||
10 | void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>, | ||
11 | int (*<[compar]>)(const void *, const void *) ); | ||
12 | |||
13 | TRAD_SYNOPSIS | ||
14 | #include <stdlib.h> | ||
15 | qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> ) | ||
16 | char *<[base]>; | ||
17 | size_t <[nmemb]>; | ||
18 | size_t <[size]>; | ||
19 | int (*<[compar]>)(); | ||
20 | |||
21 | DESCRIPTION | ||
22 | <<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects. | ||
23 | <[size]> describes the size of each element of the array. | ||
24 | |||
25 | You must supply a pointer to a comparison function, using the argument | ||
26 | shown as <[compar]>. (This permits sorting objects of unknown | ||
27 | properties.) Define the comparison function to accept two arguments, | ||
28 | each a pointer to an element of the array starting at <[base]>. The | ||
29 | result of <<(*<[compar]>)>> must be negative if the first argument is | ||
30 | less than the second, zero if the two arguments match, and positive if | ||
31 | the first argument is greater than the second (where ``less than'' and | ||
32 | ``greater than'' refer to whatever arbitrary ordering is appropriate). | ||
33 | |||
34 | The array is sorted in place; that is, when <<qsort>> returns, the | ||
35 | array elements beginning at <[base]> have been reordered. | ||
36 | |||
37 | RETURNS | ||
38 | <<qsort>> does not return a result. | ||
39 | |||
40 | PORTABILITY | ||
41 | <<qsort>> is required by ANSI (without specifying the sorting algorithm). | ||
42 | */ | ||
43 | |||
44 | /*- | ||
45 | * Copyright (c) 1992, 1993 | ||
46 | * The Regents of the University of California. All rights reserved. | ||
47 | * | ||
48 | * Redistribution and use in source and binary forms, with or without | ||
49 | * modification, are permitted provided that the following conditions | ||
50 | * are met: | ||
51 | * 1. Redistributions of source code must retain the above copyright | ||
52 | * notice, this list of conditions and the following disclaimer. | ||
53 | * 2. Redistributions in binary form must reproduce the above copyright | ||
54 | * notice, this list of conditions and the following disclaimer in the | ||
55 | * documentation and/or other materials provided with the distribution. | ||
56 | * 3. All advertising materials mentioning features or use of this software | ||
57 | * must display the following acknowledgement: | ||
58 | * This product includes software developed by the University of | ||
59 | * California, Berkeley and its contributors. | ||
60 | * 4. Neither the name of the University nor the names of its contributors | ||
61 | * may be used to endorse or promote products derived from this software | ||
62 | * without specific prior written permission. | ||
63 | * | ||
64 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
65 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
66 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
68 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
69 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
70 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
71 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
72 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
73 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
74 | * SUCH DAMAGE. | ||
75 | */ | ||
76 | |||
77 | #include <_ansi.h> | ||
78 | #include <stdlib.h> | ||
79 | |||
80 | #ifndef __GNUC__ | ||
81 | #define inline | ||
82 | #endif | ||
83 | |||
84 | static inline char *med3 _PARAMS((char *, char *, char *, int (*cmp)(const _PTR,const _PTR))); | ||
85 | static inline void swapfunc _PARAMS((char *, char *, int, int)); | ||
86 | |||
87 | #define min(a, b) (a) < (b) ? a : b | ||
88 | |||
89 | /* | ||
90 | * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". | ||
91 | */ | ||
92 | #define swapcode(TYPE, parmi, parmj, n) { \ | ||
93 | long i = (n) / sizeof (TYPE); \ | ||
94 | register TYPE *pi = (TYPE *) (parmi); \ | ||
95 | register TYPE *pj = (TYPE *) (parmj); \ | ||
96 | do { \ | ||
97 | register TYPE t = *pi; \ | ||
98 | *pi++ = *pj; \ | ||
99 | *pj++ = t; \ | ||
100 | } while (--i > 0); \ | ||
101 | } | ||
102 | |||
103 | #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ | ||
104 | es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; | ||
105 | |||
106 | static inline void | ||
107 | _DEFUN(swapfunc, (a, b, n, swaptype), | ||
108 | char *a _AND | ||
109 | char *b _AND | ||
110 | int n _AND | ||
111 | int swaptype) | ||
112 | { | ||
113 | if(swaptype <= 1) | ||
114 | swapcode(long, a, b, n) | ||
115 | else | ||
116 | swapcode(char, a, b, n) | ||
117 | } | ||
118 | |||
119 | #define swap(a, b) \ | ||
120 | if (swaptype == 0) { \ | ||
121 | long t = *(long *)(a); \ | ||
122 | *(long *)(a) = *(long *)(b); \ | ||
123 | *(long *)(b) = t; \ | ||
124 | } else \ | ||
125 | swapfunc(a, b, es, swaptype) | ||
126 | |||
127 | #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) | ||
128 | |||
129 | static inline char * | ||
130 | _DEFUN(med3, (a, b, c, cmp), | ||
131 | char *a _AND | ||
132 | char *b _AND | ||
133 | char *c _AND | ||
134 | int (*cmp)(const _PTR,const _PTR)) | ||
135 | { | ||
136 | return cmp(a, b) < 0 ? | ||
137 | (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) | ||
138 | :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); | ||
139 | } | ||
140 | |||
141 | void | ||
142 | _DEFUN(qsort, (a, n, es, cmp), | ||
143 | void *a _AND | ||
144 | size_t n _AND | ||
145 | size_t es _AND | ||
146 | int (*cmp)(const _PTR,const _PTR)) | ||
147 | { | ||
148 | char *pa, *pb, *pc, *pd, *pl, *pm, *pn; | ||
149 | int d, r, swaptype, swap_cnt; | ||
150 | |||
151 | loop: SWAPINIT(a, es); | ||
152 | swap_cnt = 0; | ||
153 | if (n < 7) { | ||
154 | for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) | ||
155 | for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; | ||
156 | pl -= es) | ||
157 | swap(pl, pl - es); | ||
158 | return; | ||
159 | } | ||
160 | pm = (char *) a + (n / 2) * es; | ||
161 | if (n > 7) { | ||
162 | pl = a; | ||
163 | pn = (char *) a + (n - 1) * es; | ||
164 | if (n > 40) { | ||
165 | d = (n / 8) * es; | ||
166 | pl = med3(pl, pl + d, pl + 2 * d, cmp); | ||
167 | pm = med3(pm - d, pm, pm + d, cmp); | ||
168 | pn = med3(pn - 2 * d, pn - d, pn, cmp); | ||
169 | } | ||
170 | pm = med3(pl, pm, pn, cmp); | ||
171 | } | ||
172 | swap(a, pm); | ||
173 | pa = pb = (char *) a + es; | ||
174 | |||
175 | pc = pd = (char *) a + (n - 1) * es; | ||
176 | for (;;) { | ||
177 | while (pb <= pc && (r = cmp(pb, a)) <= 0) { | ||
178 | if (r == 0) { | ||
179 | swap_cnt = 1; | ||
180 | swap(pa, pb); | ||
181 | pa += es; | ||
182 | } | ||
183 | pb += es; | ||
184 | } | ||
185 | while (pb <= pc && (r = cmp(pc, a)) >= 0) { | ||
186 | if (r == 0) { | ||
187 | swap_cnt = 1; | ||
188 | swap(pc, pd); | ||
189 | pd -= es; | ||
190 | } | ||
191 | pc -= es; | ||
192 | } | ||
193 | if (pb > pc) | ||
194 | break; | ||
195 | swap(pb, pc); | ||
196 | swap_cnt = 1; | ||
197 | pb += es; | ||
198 | pc -= es; | ||
199 | } | ||
200 | if (swap_cnt == 0) { /* Switch to insertion sort */ | ||
201 | for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) | ||
202 | for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; | ||
203 | pl -= es) | ||
204 | swap(pl, pl - es); | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | pn = (char *) a + n * es; | ||
209 | r = min(pa - (char *)a, pb - pa); | ||
210 | vecswap(a, pb - r, r); | ||
211 | r = min((unsigned int)(pd - pc), pn - pd - es); | ||
212 | vecswap(pb, pn - r, r); | ||
213 | if ((unsigned int)(r = pb - pa) > es) | ||
214 | qsort(a, r / es, es, cmp); | ||
215 | if ((unsigned int)(r = pd - pc) > es) { | ||
216 | /* Iterate rather than recurse to save stack space */ | ||
217 | a = pn - r; | ||
218 | n = r / es; | ||
219 | goto loop; | ||
220 | } | ||
221 | /* qsort(pn - r, r / es, es, cmp);*/ | ||
222 | } | ||
diff --git a/firmware/libc/random.c b/firmware/libc/random.c new file mode 100644 index 0000000000..f3efe89351 --- /dev/null +++ b/firmware/libc/random.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | A C-program for MT19937, with initialization improved 2002/2/10. | ||
3 | Coded by Takuji Nishimura and Makoto Matsumoto. | ||
4 | This is a faster version by taking Shawn Cokus's optimization, | ||
5 | Matthe Bellew's simplification. | ||
6 | |||
7 | Before using, initialize the state by using srand(seed). | ||
8 | |||
9 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, | ||
10 | All rights reserved. | ||
11 | |||
12 | Redistribution and use in source and binary forms, with or without | ||
13 | modification, are permitted provided that the following conditions | ||
14 | are met: | ||
15 | |||
16 | 1. Redistributions of source code must retain the above copyright | ||
17 | notice, this list of conditions and the following disclaimer. | ||
18 | |||
19 | 2. Redistributions in binary form must reproduce the above copyright | ||
20 | notice, this list of conditions and the following disclaimer in the | ||
21 | documentation and/or other materials provided with the distribution. | ||
22 | |||
23 | 3. The names of its contributors may not be used to endorse or promote | ||
24 | products derived from this software without specific prior written | ||
25 | permission. | ||
26 | |||
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
31 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
32 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
33 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
34 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
35 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
36 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | |||
39 | Any feedback is very welcome. | ||
40 | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html | ||
41 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) | ||
42 | */ | ||
43 | |||
44 | /* | ||
45 | Adapted to Rockbox by Jens Arnold | ||
46 | */ | ||
47 | |||
48 | #include <stdlib.h> | ||
49 | |||
50 | /* Period parameters */ | ||
51 | #define N 624 | ||
52 | #define M 397 | ||
53 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ | ||
54 | #define UMASK 0x80000000UL /* most significant w-r bits */ | ||
55 | #define LMASK 0x7fffffffUL /* least significant r bits */ | ||
56 | #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) | ||
57 | #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) | ||
58 | |||
59 | static unsigned long state[N]; /* the array for the state vector */ | ||
60 | static int left = 0; | ||
61 | static unsigned long *next; | ||
62 | |||
63 | /* initializes state[N] with a seed */ | ||
64 | void srand(unsigned int seed) | ||
65 | { | ||
66 | unsigned long x = seed & 0xffffffffUL; | ||
67 | unsigned long *s = state; | ||
68 | int j; | ||
69 | |||
70 | for (*s++ = x, j = 1; j < N; j++) { | ||
71 | x = (1812433253UL * (x ^ (x >> 30)) + j) & 0xffffffffUL; | ||
72 | *s++ = x; | ||
73 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ | ||
74 | /* In the previous versions, MSBs of the seed affect */ | ||
75 | /* only MSBs of the array state[]. */ | ||
76 | /* 2002/01/09 modified by Makoto Matsumoto */ | ||
77 | } | ||
78 | left = 1; | ||
79 | } | ||
80 | |||
81 | static void next_state(void) | ||
82 | { | ||
83 | unsigned long *p = state; | ||
84 | int j; | ||
85 | |||
86 | /* if srand() has not been called, */ | ||
87 | /* a default initial seed is used */ | ||
88 | if (left < 0) | ||
89 | srand(5489UL); | ||
90 | |||
91 | left = N; | ||
92 | next = state; | ||
93 | |||
94 | for (j = N - M + 1; --j; p++) | ||
95 | *p = p[M] ^ TWIST(p[0], p[1]); | ||
96 | |||
97 | for (j = M; --j; p++) | ||
98 | *p = p[M-N] ^ TWIST(p[0], p[1]); | ||
99 | |||
100 | *p = p[M-N] ^ TWIST(p[0], state[0]); | ||
101 | } | ||
102 | |||
103 | /* generates a random number on [0,RAND_MAX]-interval */ | ||
104 | int rand(void) | ||
105 | { | ||
106 | unsigned long y; | ||
107 | |||
108 | if (--left <= 0) | ||
109 | next_state(); | ||
110 | y = *next++; | ||
111 | |||
112 | /* Tempering */ | ||
113 | y ^= (y >> 11); | ||
114 | y ^= (y << 7) & 0x9d2c5680UL; | ||
115 | y ^= (y << 15) & 0xefc60000UL; | ||
116 | y ^= (y >> 18); | ||
117 | |||
118 | return ((unsigned int)y) >> 1; | ||
119 | } | ||
diff --git a/firmware/libc/sprintf.c b/firmware/libc/sprintf.c new file mode 100644 index 0000000000..b02f5a2fae --- /dev/null +++ b/firmware/libc/sprintf.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Gary Czvitkovicz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* | ||
23 | * Minimal printf and snprintf formatting functions | ||
24 | * | ||
25 | * These support %c %s %d and %x | ||
26 | * Field width and zero-padding flag only | ||
27 | */ | ||
28 | |||
29 | #include <stdio.h> | ||
30 | #include <stdarg.h> | ||
31 | #include <stdbool.h> | ||
32 | #include <limits.h> | ||
33 | #include "format.h" | ||
34 | |||
35 | /* ALSA library requires a more advanced snprintf, so let's not | ||
36 | override it in simulator for Linux. Note that Cygwin requires | ||
37 | our snprintf or it produces garbled output after a while. */ | ||
38 | |||
39 | struct for_snprintf { | ||
40 | unsigned char *ptr; /* where to store it */ | ||
41 | size_t bytes; /* amount already stored */ | ||
42 | size_t max; /* max amount to store */ | ||
43 | }; | ||
44 | |||
45 | static int sprfunc(void *ptr, unsigned char letter) | ||
46 | { | ||
47 | struct for_snprintf *pr = (struct for_snprintf *)ptr; | ||
48 | if(pr->bytes < pr->max) { | ||
49 | *pr->ptr = letter; | ||
50 | pr->ptr++; | ||
51 | pr->bytes++; | ||
52 | return true; | ||
53 | } | ||
54 | return false; /* filled buffer */ | ||
55 | } | ||
56 | |||
57 | |||
58 | int snprintf(char *buf, size_t size, const char *fmt, ...) | ||
59 | { | ||
60 | bool ok; | ||
61 | va_list ap; | ||
62 | struct for_snprintf pr; | ||
63 | |||
64 | pr.ptr = (unsigned char *)buf; | ||
65 | pr.bytes = 0; | ||
66 | pr.max = size; | ||
67 | |||
68 | va_start(ap, fmt); | ||
69 | ok = format(sprfunc, &pr, fmt, ap); | ||
70 | va_end(ap); | ||
71 | |||
72 | /* make sure it ends with a trailing zero */ | ||
73 | pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0'; | ||
74 | |||
75 | return pr.bytes; | ||
76 | } | ||
77 | |||
78 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) | ||
79 | { | ||
80 | bool ok; | ||
81 | struct for_snprintf pr; | ||
82 | |||
83 | pr.ptr = (unsigned char *)buf; | ||
84 | pr.bytes = 0; | ||
85 | pr.max = size; | ||
86 | |||
87 | ok = format(sprfunc, &pr, fmt, ap); | ||
88 | |||
89 | /* make sure it ends with a trailing zero */ | ||
90 | pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0'; | ||
91 | |||
92 | return pr.bytes; | ||
93 | } | ||
diff --git a/firmware/libc/sscanf.c b/firmware/libc/sscanf.c new file mode 100644 index 0000000000..5fbe81f3e0 --- /dev/null +++ b/firmware/libc/sscanf.c | |||
@@ -0,0 +1,282 @@ | |||
1 | #include <stdarg.h> | ||
2 | #include <string.h> | ||
3 | #include <stdbool.h> | ||
4 | |||
5 | static inline bool isspace(char c) | ||
6 | { | ||
7 | return (c == ' ') || (c == '\t') || (c == '\n'); | ||
8 | } | ||
9 | |||
10 | static inline bool isdigit(char c) | ||
11 | { | ||
12 | return (c >= '0') && (c <= '9'); | ||
13 | } | ||
14 | |||
15 | static inline bool isxdigit(char c) | ||
16 | { | ||
17 | return ((c >= '0') && (c <= '9')) | ||
18 | || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')); | ||
19 | } | ||
20 | |||
21 | static int parse_dec(int (*peek)(void *userp), | ||
22 | void (*pop)(void *userp), | ||
23 | void *userp, | ||
24 | long *vp) | ||
25 | { | ||
26 | long v = 0; | ||
27 | int n = 0; | ||
28 | int minus = 0; | ||
29 | char ch; | ||
30 | |||
31 | if ((*peek)(userp) == '-') | ||
32 | { | ||
33 | (*pop)(userp); | ||
34 | n++; | ||
35 | minus = 1; | ||
36 | } | ||
37 | |||
38 | ch = (*peek)(userp); | ||
39 | if (!isdigit(ch)) | ||
40 | return -1; | ||
41 | |||
42 | do | ||
43 | { | ||
44 | v = v * 10 + ch - '0'; | ||
45 | (*pop)(userp); | ||
46 | n++; | ||
47 | ch = (*peek)(userp); | ||
48 | } while (isdigit(ch)); | ||
49 | |||
50 | *vp = minus ? -v : v; | ||
51 | return n; | ||
52 | } | ||
53 | |||
54 | static int parse_chars(int (*peek)(void *userp), | ||
55 | void (*pop)(void *userp), | ||
56 | void *userp, | ||
57 | char *vp, | ||
58 | bool fake) | ||
59 | { | ||
60 | int n = 0; | ||
61 | |||
62 | char *pt=vp; | ||
63 | |||
64 | while (!isspace((*peek)(userp))) | ||
65 | { | ||
66 | if(fake==false) | ||
67 | *(pt++) = (*peek)(userp); | ||
68 | |||
69 | n++; | ||
70 | (*pop)(userp); | ||
71 | } | ||
72 | |||
73 | if(fake==false) | ||
74 | (*pt)='\0'; | ||
75 | |||
76 | return n; | ||
77 | } | ||
78 | |||
79 | static int parse_hex(int (*peek)(void *userp), | ||
80 | void (*pop)(void *userp), | ||
81 | void *userp, | ||
82 | unsigned long *vp) | ||
83 | { | ||
84 | unsigned long v = 0; | ||
85 | int n = 0; | ||
86 | char ch; | ||
87 | |||
88 | ch = (*peek)(userp); | ||
89 | if (!isxdigit(ch)) | ||
90 | return -1; | ||
91 | |||
92 | do | ||
93 | { | ||
94 | if (ch >= 'a') | ||
95 | ch = ch - 'a' + 10; | ||
96 | else if (ch >= 'A') | ||
97 | ch = ch - 'A' + 10; | ||
98 | else | ||
99 | ch = ch - '0'; | ||
100 | v = v * 16 + ch; | ||
101 | (*pop)(userp); | ||
102 | n++; | ||
103 | ch = (*peek)(userp); | ||
104 | } while (isxdigit(ch)); | ||
105 | |||
106 | *vp = v; | ||
107 | return n; | ||
108 | } | ||
109 | |||
110 | static int skip_spaces(int (*peek)(void *userp), | ||
111 | void (*pop)(void *userp), | ||
112 | void *userp) | ||
113 | { | ||
114 | int n = 0; | ||
115 | while (isspace((*peek)(userp))) { | ||
116 | n++; | ||
117 | (*pop)(userp); | ||
118 | } | ||
119 | return n; | ||
120 | } | ||
121 | |||
122 | static int scan(int (*peek)(void *userp), | ||
123 | void (*pop)(void *userp), | ||
124 | void *userp, | ||
125 | const char *fmt, | ||
126 | va_list ap) | ||
127 | { | ||
128 | char ch; | ||
129 | int n = 0; | ||
130 | int n_chars = 0; | ||
131 | int r; | ||
132 | long lval; | ||
133 | bool skip=false; | ||
134 | unsigned long ulval; | ||
135 | |||
136 | while ((ch = *fmt++) != '\0') | ||
137 | { | ||
138 | bool literal = false; | ||
139 | |||
140 | if (ch == '%') | ||
141 | { | ||
142 | ch = *fmt++; | ||
143 | |||
144 | if(ch== '*') /* We should process this, but not store it in an arguement */ | ||
145 | { | ||
146 | ch=*fmt++; | ||
147 | skip=true; | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | skip=false; | ||
152 | } | ||
153 | |||
154 | switch (ch) | ||
155 | { | ||
156 | case 'x': | ||
157 | n_chars += skip_spaces(peek, pop, userp); | ||
158 | if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0) | ||
159 | { | ||
160 | if(skip==false) | ||
161 | { | ||
162 | *(va_arg(ap, unsigned int *)) = ulval; | ||
163 | n++; | ||
164 | } | ||
165 | n_chars += r; | ||
166 | } | ||
167 | else | ||
168 | return n; | ||
169 | break; | ||
170 | case 'd': | ||
171 | n_chars += skip_spaces(peek, pop, userp); | ||
172 | if ((r = parse_dec(peek, pop, userp, &lval)) >= 0) | ||
173 | { | ||
174 | if(skip==false) | ||
175 | { | ||
176 | *(va_arg(ap, int *)) = lval; | ||
177 | n++; | ||
178 | } | ||
179 | n_chars += r; | ||
180 | } | ||
181 | else | ||
182 | return n; | ||
183 | break; | ||
184 | case 'n': | ||
185 | if(skip==false) | ||
186 | { | ||
187 | *(va_arg(ap, int *)) = n_chars; | ||
188 | n++; | ||
189 | } | ||
190 | break; | ||
191 | case 'l': | ||
192 | n_chars += skip_spaces(peek, pop, userp); | ||
193 | ch = *fmt++; | ||
194 | switch (ch) | ||
195 | { | ||
196 | case 'x': | ||
197 | if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0) | ||
198 | { | ||
199 | if(skip==false) | ||
200 | { | ||
201 | *(va_arg(ap, unsigned long *)) = ulval; | ||
202 | n++; | ||
203 | } | ||
204 | n_chars += r; | ||
205 | } | ||
206 | else | ||
207 | return n; | ||
208 | break; | ||
209 | case 'd': | ||
210 | if ((r = parse_dec(peek, pop, userp, &lval)) >= 0) | ||
211 | { | ||
212 | if(skip==false) | ||
213 | { | ||
214 | *(va_arg(ap, long *)) = lval; | ||
215 | n++; | ||
216 | } | ||
217 | n_chars += r; | ||
218 | } | ||
219 | else | ||
220 | return n; | ||
221 | break; | ||
222 | case '\0': | ||
223 | return n; | ||
224 | default: | ||
225 | literal = true; | ||
226 | break; | ||
227 | } | ||
228 | break; | ||
229 | case 's': | ||
230 | n_chars += skip_spaces(peek, pop, userp); | ||
231 | n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip ); | ||
232 | if(skip==false) | ||
233 | { | ||
234 | n++; | ||
235 | } | ||
236 | break; | ||
237 | case '\0': | ||
238 | return n; | ||
239 | default: | ||
240 | literal = true; | ||
241 | break; | ||
242 | } | ||
243 | } else | ||
244 | literal = true; | ||
245 | |||
246 | if (literal) | ||
247 | { | ||
248 | n_chars += skip_spaces(peek, pop, userp); | ||
249 | if ((*peek)(userp) != ch) | ||
250 | continue; | ||
251 | else | ||
252 | { | ||
253 | (*pop)(userp); | ||
254 | n_chars++; | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | return n; | ||
259 | } | ||
260 | |||
261 | static int sspeek(void *userp) | ||
262 | { | ||
263 | return **((char **)userp); | ||
264 | } | ||
265 | |||
266 | static void sspop(void *userp) | ||
267 | { | ||
268 | (*((char **)userp))++; | ||
269 | } | ||
270 | |||
271 | int sscanf(const char *s, const char *fmt, ...) | ||
272 | { | ||
273 | int r; | ||
274 | va_list ap; | ||
275 | const char *p; | ||
276 | |||
277 | p = s; | ||
278 | va_start(ap, fmt); | ||
279 | r = scan(sspeek, sspop, &p, fmt, ap); | ||
280 | va_end(ap); | ||
281 | return r; | ||
282 | } | ||
diff --git a/firmware/libc/strcat.c b/firmware/libc/strcat.c new file mode 100644 index 0000000000..221529519c --- /dev/null +++ b/firmware/libc/strcat.c | |||
@@ -0,0 +1,14 @@ | |||
1 | #include <string.h> | ||
2 | |||
3 | char *strcat(char *s1, | ||
4 | const char *s2) | ||
5 | { | ||
6 | char *s = s1; | ||
7 | |||
8 | while (*s1) | ||
9 | s1++; | ||
10 | |||
11 | while ((*s1++ = *s2++)) | ||
12 | ; | ||
13 | return s; | ||
14 | } | ||
diff --git a/firmware/libc/strchr.c b/firmware/libc/strchr.c new file mode 100644 index 0000000000..96acf5edf6 --- /dev/null +++ b/firmware/libc/strchr.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strchr>>---search for character in string | ||
4 | |||
5 | INDEX | ||
6 | strchr | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | char * strchr(const char *<[string]>, int <[c]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | char * strchr(<[string]>, <[c]>); | ||
15 | char *<[string]>; | ||
16 | int *<[c]>; | ||
17 | |||
18 | DESCRIPTION | ||
19 | This function finds the first occurence of <[c]> (converted to | ||
20 | a char) in the string pointed to by <[string]> (including the | ||
21 | terminating null character). | ||
22 | |||
23 | RETURNS | ||
24 | Returns a pointer to the located character, or a null pointer | ||
25 | if <[c]> does not occur in <[string]>. | ||
26 | |||
27 | PORTABILITY | ||
28 | <<strchr>> is ANSI C. | ||
29 | |||
30 | <<strchr>> requires no supporting OS subroutines. | ||
31 | |||
32 | QUICKREF | ||
33 | strchr ansi pure | ||
34 | */ | ||
35 | |||
36 | #include <string.h> | ||
37 | #include <limits.h> | ||
38 | |||
39 | /* Nonzero if X is not aligned on a "long" boundary. */ | ||
40 | #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) | ||
41 | |||
42 | /* How many bytes are loaded each iteration of the word copy loop. */ | ||
43 | #define LBLOCKSIZE (sizeof (long)) | ||
44 | |||
45 | #if LONG_MAX == 2147483647L | ||
46 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
47 | #else | ||
48 | #if LONG_MAX == 9223372036854775807L | ||
49 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
50 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
51 | #else | ||
52 | #error long int is not a 32bit or 64bit type. | ||
53 | #endif | ||
54 | #endif | ||
55 | |||
56 | /* DETECTCHAR returns nonzero if (long)X contains the byte used | ||
57 | to fill (long)MASK. */ | ||
58 | #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) | ||
59 | |||
60 | char * | ||
61 | _DEFUN (strchr, (s1, i), | ||
62 | _CONST char *s1 _AND | ||
63 | int i) | ||
64 | { | ||
65 | _CONST unsigned char *s = (_CONST unsigned char *)s1; | ||
66 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
67 | unsigned char c = (unsigned int)i; | ||
68 | |||
69 | while (*s && *s != c) | ||
70 | { | ||
71 | s++; | ||
72 | } | ||
73 | |||
74 | if (*s != c) | ||
75 | { | ||
76 | s = NULL; | ||
77 | } | ||
78 | |||
79 | return (char *) s; | ||
80 | #else | ||
81 | unsigned char c = (unsigned char)i; | ||
82 | unsigned long mask,j; | ||
83 | unsigned long *aligned_addr; | ||
84 | |||
85 | if (!UNALIGNED (s)) | ||
86 | { | ||
87 | mask = 0; | ||
88 | for (j = 0; j < LBLOCKSIZE; j++) | ||
89 | mask = (mask << 8) | c; | ||
90 | |||
91 | aligned_addr = (unsigned long*)s; | ||
92 | while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) | ||
93 | aligned_addr++; | ||
94 | |||
95 | /* The block of bytes currently pointed to by aligned_addr | ||
96 | contains either a null or the target char, or both. We | ||
97 | catch it using the bytewise search. */ | ||
98 | |||
99 | s = (unsigned char*)aligned_addr; | ||
100 | } | ||
101 | |||
102 | while (*s && *s != c) | ||
103 | s++; | ||
104 | if (*s == c) | ||
105 | return (char *)s; | ||
106 | return NULL; | ||
107 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
108 | } | ||
diff --git a/firmware/libc/strcmp.c b/firmware/libc/strcmp.c new file mode 100644 index 0000000000..bbbf4b174a --- /dev/null +++ b/firmware/libc/strcmp.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strcmp>>---character string compare | ||
4 | |||
5 | INDEX | ||
6 | strcmp | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | int strcmp(const char *<[a]>, const char *<[b]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | int strcmp(<[a]>, <[b]>) | ||
15 | char *<[a]>; | ||
16 | char *<[b]>; | ||
17 | |||
18 | DESCRIPTION | ||
19 | <<strcmp>> compares the string at <[a]> to | ||
20 | the string at <[b]>. | ||
21 | |||
22 | RETURNS | ||
23 | If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, | ||
24 | <<strcmp>> returns a number greater than zero. If the two | ||
25 | strings match, <<strcmp>> returns zero. If <<*<[a]>>> | ||
26 | sorts lexicographically before <<*<[b]>>>, <<strcmp>> returns a | ||
27 | number less than zero. | ||
28 | |||
29 | PORTABILITY | ||
30 | <<strcmp>> is ANSI C. | ||
31 | |||
32 | <<strcmp>> requires no supporting OS subroutines. | ||
33 | |||
34 | QUICKREF | ||
35 | strcmp ansi pure | ||
36 | */ | ||
37 | |||
38 | #include <string.h> | ||
39 | #include <limits.h> | ||
40 | |||
41 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
42 | #define UNALIGNED(X, Y) \ | ||
43 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
44 | |||
45 | /* DETECTNULL returns nonzero if (long)X contains a NULL byte. */ | ||
46 | #if LONG_MAX == 2147483647L | ||
47 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
48 | #else | ||
49 | #if LONG_MAX == 9223372036854775807L | ||
50 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
51 | #else | ||
52 | #error long int is not a 32bit or 64bit type. | ||
53 | #endif | ||
54 | #endif | ||
55 | |||
56 | #ifndef DETECTNULL | ||
57 | #error long int is not a 32bit or 64bit byte | ||
58 | #endif | ||
59 | |||
60 | int | ||
61 | _DEFUN (strcmp, (s1, s2), | ||
62 | _CONST char *s1 _AND | ||
63 | _CONST char *s2) | ||
64 | { | ||
65 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
66 | while (*s1 != '\0' && *s1 == *s2) | ||
67 | { | ||
68 | s1++; | ||
69 | s2++; | ||
70 | } | ||
71 | |||
72 | return (*(unsigned char *) s1) - (*(unsigned char *) s2); | ||
73 | #else | ||
74 | unsigned long *a1; | ||
75 | unsigned long *a2; | ||
76 | |||
77 | /* If s1 or s2 are unaligned, then compare bytes. */ | ||
78 | if (!UNALIGNED (s1, s2)) | ||
79 | { | ||
80 | /* If s1 and s2 are word-aligned, compare them a word at a time. */ | ||
81 | a1 = (unsigned long*)s1; | ||
82 | a2 = (unsigned long*)s2; | ||
83 | while (*a1 == *a2) | ||
84 | { | ||
85 | /* To get here, *a1 == *a2, thus if we find a null in *a1, | ||
86 | then the strings must be equal, so return zero. */ | ||
87 | if (DETECTNULL (*a1)) | ||
88 | return 0; | ||
89 | |||
90 | a1++; | ||
91 | a2++; | ||
92 | } | ||
93 | |||
94 | /* A difference was detected in last few bytes of s1, so search bytewise */ | ||
95 | s1 = (char*)a1; | ||
96 | s2 = (char*)a2; | ||
97 | } | ||
98 | |||
99 | while (*s1 != '\0' && *s1 == *s2) | ||
100 | { | ||
101 | s1++; | ||
102 | s2++; | ||
103 | } | ||
104 | return (*(unsigned char *) s1) - (*(unsigned char *) s2); | ||
105 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
106 | } | ||
diff --git a/firmware/libc/strcpy.c b/firmware/libc/strcpy.c new file mode 100644 index 0000000000..077ae73cc6 --- /dev/null +++ b/firmware/libc/strcpy.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strcpy>>---copy string | ||
4 | |||
5 | INDEX | ||
6 | strcpy | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | char *strcpy(char *<[dst]>, const char *<[src]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | char *strcpy(<[dst]>, <[src]>) | ||
15 | char *<[dst]>; | ||
16 | char *<[src]>; | ||
17 | |||
18 | DESCRIPTION | ||
19 | <<strcpy>> copies the string pointed to by <[src]> | ||
20 | (including the terminating null character) to the array | ||
21 | pointed to by <[dst]>. | ||
22 | |||
23 | RETURNS | ||
24 | This function returns the initial value of <[dst]>. | ||
25 | |||
26 | PORTABILITY | ||
27 | <<strcpy>> is ANSI C. | ||
28 | |||
29 | <<strcpy>> requires no supporting OS subroutines. | ||
30 | |||
31 | QUICKREF | ||
32 | strcpy ansi pure | ||
33 | */ | ||
34 | |||
35 | #include <string.h> | ||
36 | #include <limits.h> | ||
37 | |||
38 | /*SUPPRESS 560*/ | ||
39 | /*SUPPRESS 530*/ | ||
40 | |||
41 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
42 | #define UNALIGNED(X, Y) \ | ||
43 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
44 | |||
45 | #if LONG_MAX == 2147483647L | ||
46 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
47 | #else | ||
48 | #if LONG_MAX == 9223372036854775807L | ||
49 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
50 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
51 | #else | ||
52 | #error long int is not a 32bit or 64bit type. | ||
53 | #endif | ||
54 | #endif | ||
55 | |||
56 | #ifndef DETECTNULL | ||
57 | #error long int is not a 32bit or 64bit byte | ||
58 | #endif | ||
59 | |||
60 | char* | ||
61 | _DEFUN (strcpy, (dst0, src0), | ||
62 | char *dst0 _AND | ||
63 | _CONST char *src0) | ||
64 | { | ||
65 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
66 | char *s = dst0; | ||
67 | |||
68 | while ((*dst0++ = *src0++)) | ||
69 | ; | ||
70 | |||
71 | return s; | ||
72 | #else | ||
73 | char *dst = dst0; | ||
74 | _CONST char *src = src0; | ||
75 | long *aligned_dst; | ||
76 | _CONST long *aligned_src; | ||
77 | |||
78 | /* If SRC or DEST is unaligned, then copy bytes. */ | ||
79 | if (!UNALIGNED (src, dst)) | ||
80 | { | ||
81 | aligned_dst = (long*)dst; | ||
82 | aligned_src = (long*)src; | ||
83 | |||
84 | /* SRC and DEST are both "long int" aligned, try to do "long int" | ||
85 | sized copies. */ | ||
86 | while (!DETECTNULL(*aligned_src)) | ||
87 | { | ||
88 | *aligned_dst++ = *aligned_src++; | ||
89 | } | ||
90 | |||
91 | dst = (char*)aligned_dst; | ||
92 | src = (char*)aligned_src; | ||
93 | } | ||
94 | |||
95 | while ((*dst++ = *src++)) | ||
96 | ; | ||
97 | return dst0; | ||
98 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
99 | } | ||
diff --git a/firmware/libc/strlen.c b/firmware/libc/strlen.c new file mode 100644 index 0000000000..4d33eafce6 --- /dev/null +++ b/firmware/libc/strlen.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strlen>>---character string length | ||
4 | |||
5 | INDEX | ||
6 | strlen | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | size_t strlen(const char *<[str]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | size_t strlen(<[str]>) | ||
15 | char *<[src]>; | ||
16 | |||
17 | DESCRIPTION | ||
18 | The <<strlen>> function works out the length of the string | ||
19 | starting at <<*<[str]>>> by counting chararacters until it | ||
20 | reaches a <<NULL>> character. | ||
21 | |||
22 | RETURNS | ||
23 | <<strlen>> returns the character count. | ||
24 | |||
25 | PORTABILITY | ||
26 | <<strlen>> is ANSI C. | ||
27 | |||
28 | <<strlen>> requires no supporting OS subroutines. | ||
29 | |||
30 | QUICKREF | ||
31 | strlen ansi pure | ||
32 | */ | ||
33 | |||
34 | #include "config.h" | ||
35 | #include <_ansi.h> | ||
36 | #include <string.h> | ||
37 | #include <limits.h> | ||
38 | |||
39 | #define LBLOCKSIZE (sizeof (long)) | ||
40 | #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) | ||
41 | |||
42 | #if LONG_MAX == 2147483647L | ||
43 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
44 | #else | ||
45 | #if LONG_MAX == 9223372036854775807L | ||
46 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
47 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
48 | #else | ||
49 | #error long int is not a 32bit or 64bit type. | ||
50 | #endif | ||
51 | #endif | ||
52 | |||
53 | #ifndef DETECTNULL | ||
54 | #error long int is not a 32bit or 64bit byte | ||
55 | #endif | ||
56 | |||
57 | size_t | ||
58 | _DEFUN (strlen, (str), | ||
59 | _CONST char *str) ICODE_ATTR; | ||
60 | |||
61 | size_t | ||
62 | _DEFUN (strlen, (str), | ||
63 | _CONST char *str) | ||
64 | { | ||
65 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
66 | _CONST char *start = str; | ||
67 | |||
68 | while (*str) | ||
69 | str++; | ||
70 | |||
71 | return str - start; | ||
72 | #else | ||
73 | _CONST char *start = str; | ||
74 | unsigned long *aligned_addr; | ||
75 | |||
76 | if (!UNALIGNED (str)) | ||
77 | { | ||
78 | /* If the string is word-aligned, we can check for the presence of | ||
79 | a null in each word-sized block. */ | ||
80 | aligned_addr = (unsigned long*)str; | ||
81 | while (!DETECTNULL (*aligned_addr)) | ||
82 | aligned_addr++; | ||
83 | |||
84 | /* Once a null is detected, we check each byte in that block for a | ||
85 | precise position of the null. */ | ||
86 | str = (char*)aligned_addr; | ||
87 | } | ||
88 | |||
89 | while (*str) | ||
90 | str++; | ||
91 | return str - start; | ||
92 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
93 | } | ||
diff --git a/firmware/libc/strncmp.c b/firmware/libc/strncmp.c new file mode 100644 index 0000000000..b1d8d9d43a --- /dev/null +++ b/firmware/libc/strncmp.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strncmp>>---character string compare | ||
4 | |||
5 | INDEX | ||
6 | strncmp | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | int strncmp(<[a]>, <[b]>, <[length]>) | ||
15 | char *<[a]>; | ||
16 | char *<[b]>; | ||
17 | size_t <[length]> | ||
18 | |||
19 | DESCRIPTION | ||
20 | <<strncmp>> compares up to <[length]> characters | ||
21 | from the string at <[a]> to the string at <[b]>. | ||
22 | |||
23 | RETURNS | ||
24 | If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, | ||
25 | <<strncmp>> returns a number greater than zero. If the two | ||
26 | strings are equivalent, <<strncmp>> returns zero. If <<*<[a]>>> | ||
27 | sorts lexicographically before <<*<[b]>>>, <<strncmp>> returns a | ||
28 | number less than zero. | ||
29 | |||
30 | PORTABILITY | ||
31 | <<strncmp>> is ANSI C. | ||
32 | |||
33 | <<strncmp>> requires no supporting OS subroutines. | ||
34 | |||
35 | QUICKREF | ||
36 | strncmp ansi pure | ||
37 | */ | ||
38 | |||
39 | #include <string.h> | ||
40 | #include <limits.h> | ||
41 | |||
42 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
43 | #define UNALIGNED(X, Y) \ | ||
44 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
45 | |||
46 | /* DETECTNULL returns nonzero if (long)X contains a NULL byte. */ | ||
47 | #if LONG_MAX == 2147483647L | ||
48 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
49 | #else | ||
50 | #if LONG_MAX == 9223372036854775807L | ||
51 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
52 | #else | ||
53 | #error long int is not a 32bit or 64bit type. | ||
54 | #endif | ||
55 | #endif | ||
56 | |||
57 | #ifndef DETECTNULL | ||
58 | #error long int is not a 32bit or 64bit byte | ||
59 | #endif | ||
60 | |||
61 | int | ||
62 | _DEFUN (strncmp, (s1, s2, n), | ||
63 | _CONST char *s1 _AND | ||
64 | _CONST char *s2 _AND | ||
65 | size_t n) | ||
66 | { | ||
67 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
68 | if (n == 0) | ||
69 | return 0; | ||
70 | |||
71 | while (n-- != 0 && *s1 == *s2) | ||
72 | { | ||
73 | if (n == 0 || *s1 == '\0') | ||
74 | break; | ||
75 | s1++; | ||
76 | s2++; | ||
77 | } | ||
78 | |||
79 | return (*(unsigned char *) s1) - (*(unsigned char *) s2); | ||
80 | #else | ||
81 | unsigned long *a1; | ||
82 | unsigned long *a2; | ||
83 | |||
84 | if (n == 0) | ||
85 | return 0; | ||
86 | |||
87 | /* If s1 or s2 are unaligned, then compare bytes. */ | ||
88 | if (!UNALIGNED (s1, s2)) | ||
89 | { | ||
90 | /* If s1 and s2 are word-aligned, compare them a word at a time. */ | ||
91 | a1 = (unsigned long*)s1; | ||
92 | a2 = (unsigned long*)s2; | ||
93 | while (n >= sizeof (long) && *a1 == *a2) | ||
94 | { | ||
95 | n -= sizeof (long); | ||
96 | |||
97 | /* If we've run out of bytes or hit a null, return zero | ||
98 | since we already know *a1 == *a2. */ | ||
99 | if (n == 0 || DETECTNULL (*a1)) | ||
100 | return 0; | ||
101 | |||
102 | a1++; | ||
103 | a2++; | ||
104 | } | ||
105 | |||
106 | /* A difference was detected in last few bytes of s1, so search bytewise */ | ||
107 | s1 = (char*)a1; | ||
108 | s2 = (char*)a2; | ||
109 | } | ||
110 | |||
111 | while (n-- > 0 && *s1 == *s2) | ||
112 | { | ||
113 | /* If we've run out of bytes or hit a null, return zero | ||
114 | since we already know *s1 == *s2. */ | ||
115 | if (n == 0 || *s1 == '\0') | ||
116 | return 0; | ||
117 | s1++; | ||
118 | s2++; | ||
119 | } | ||
120 | return (*(unsigned char *) s1) - (*(unsigned char *) s2); | ||
121 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
122 | } | ||
diff --git a/firmware/libc/strrchr.c b/firmware/libc/strrchr.c new file mode 100644 index 0000000000..31b0d049b3 --- /dev/null +++ b/firmware/libc/strrchr.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strrchr>>---reverse search for character in string | ||
4 | |||
5 | INDEX | ||
6 | strrchr | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | char * strrchr(const char *<[string]>, int <[c]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | char * strrchr(<[string]>, <[c]>); | ||
15 | char *<[string]>; | ||
16 | int *<[c]>; | ||
17 | |||
18 | DESCRIPTION | ||
19 | This function finds the last occurence of <[c]> (converted to | ||
20 | a char) in the string pointed to by <[string]> (including the | ||
21 | terminating null character). | ||
22 | |||
23 | RETURNS | ||
24 | Returns a pointer to the located character, or a null pointer | ||
25 | if <[c]> does not occur in <[string]>. | ||
26 | |||
27 | PORTABILITY | ||
28 | <<strrchr>> is ANSI C. | ||
29 | |||
30 | <<strrchr>> requires no supporting OS subroutines. | ||
31 | |||
32 | QUICKREF | ||
33 | strrchr ansi pure | ||
34 | */ | ||
35 | |||
36 | #include <string.h> | ||
37 | |||
38 | char * | ||
39 | _DEFUN (strrchr, (s, i), | ||
40 | _CONST char *s _AND | ||
41 | int i) | ||
42 | { | ||
43 | _CONST char *last = NULL; | ||
44 | |||
45 | if (i) | ||
46 | { | ||
47 | while ((s=strchr(s, i))) | ||
48 | { | ||
49 | last = s; | ||
50 | s++; | ||
51 | } | ||
52 | } | ||
53 | else | ||
54 | { | ||
55 | last = strchr(s, i); | ||
56 | } | ||
57 | |||
58 | return (char *) last; | ||
59 | } | ||
diff --git a/firmware/libc/strstr.c b/firmware/libc/strstr.c new file mode 100644 index 0000000000..73fab1cc63 --- /dev/null +++ b/firmware/libc/strstr.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
11 | * (from linux/lib/string.c) | ||
12 | * | ||
13 | ****************************************************************************/ | ||
14 | |||
15 | #include <string.h> | ||
16 | |||
17 | /** | ||
18 | * strstr - Find the first substring in a %NUL terminated string | ||
19 | * @s1: The string to be searched | ||
20 | * @s2: The string to search for | ||
21 | */ | ||
22 | char *strstr(const char *s1, const char *s2) | ||
23 | { | ||
24 | int l1, l2; | ||
25 | |||
26 | l2 = strlen(s2); | ||
27 | if (!l2) | ||
28 | return (char *)s1; | ||
29 | l1 = strlen(s1); | ||
30 | while (l1 >= l2) { | ||
31 | l1--; | ||
32 | if (!memcmp(s1, s2, l2)) | ||
33 | return (char *)s1; | ||
34 | s1++; | ||
35 | } | ||
36 | return NULL; | ||
37 | } | ||
38 | |||
diff --git a/firmware/libc/strtok.c b/firmware/libc/strtok.c new file mode 100644 index 0000000000..9e2eddf599 --- /dev/null +++ b/firmware/libc/strtok.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Daniel Stenberg | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. * | ||
19 | ****************************************************************************/ | ||
20 | |||
21 | #include "config.h" | ||
22 | |||
23 | #ifndef HAVE_STRTOK_R | ||
24 | #include <stddef.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | char * | ||
28 | strtok_r(char *ptr, const char *sep, char **end) | ||
29 | { | ||
30 | if (!ptr) | ||
31 | /* we got NULL input so then we get our last position instead */ | ||
32 | ptr = *end; | ||
33 | |||
34 | /* pass all letters that are including in the separator string */ | ||
35 | while (*ptr && strchr(sep, *ptr)) | ||
36 | ++ptr; | ||
37 | |||
38 | if (*ptr) { | ||
39 | /* so this is where the next piece of string starts */ | ||
40 | char *start = ptr; | ||
41 | |||
42 | /* set the end pointer to the first byte after the start */ | ||
43 | *end = start + 1; | ||
44 | |||
45 | /* scan through the string to find where it ends, it ends on a | ||
46 | null byte or a character that exists in the separator string */ | ||
47 | while (**end && !strchr(sep, **end)) | ||
48 | ++*end; | ||
49 | |||
50 | if (**end) { | ||
51 | /* the end is not a null byte */ | ||
52 | **end = '\0'; /* zero terminate it! */ | ||
53 | ++*end; /* advance last pointer to beyond the null byte */ | ||
54 | } | ||
55 | |||
56 | return start; /* return the position where the string starts */ | ||
57 | } | ||
58 | |||
59 | /* we ended up on a null byte, there are no more strings to find! */ | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | #endif /* this was only compiled if strtok_r wasn't present */ | ||