diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-05-30 21:03:17 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-05-30 21:03:17 +0000 |
commit | b69338f9f8ae2ae957949a0f4af9749ebb4adc3f (patch) | |
tree | c29019589ce21007d1ff99dd74d3115f19dbd3f4 | |
parent | 80361f88818ad1ce2ebc00a10f7aa8de1605b3a5 (diff) | |
download | rockbox-b69338f9f8ae2ae957949a0f4af9749ebb4adc3f.tar.gz rockbox-b69338f9f8ae2ae957949a0f4af9749ebb4adc3f.zip |
Added code from libc instead of requiring newlib
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@835 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/common/errno.c | 1 | ||||
-rw-r--r-- | firmware/common/errno.h | 134 | ||||
-rw-r--r-- | firmware/common/memcpy.c | 111 | ||||
-rw-r--r-- | firmware/common/memset.c | 109 | ||||
-rw-r--r-- | firmware/common/qsort.c | 222 | ||||
-rw-r--r-- | firmware/common/strchr.c | 108 | ||||
-rw-r--r-- | firmware/common/strcmp.c | 106 | ||||
-rw-r--r-- | firmware/common/strcpy.c | 99 | ||||
-rw-r--r-- | firmware/common/strlen.c | 88 | ||||
-rw-r--r-- | firmware/common/strncmp.c | 122 | ||||
-rw-r--r-- | firmware/common/strncpy.c | 125 | ||||
-rw-r--r-- | firmware/common/strrchr.c | 59 |
12 files changed, 1284 insertions, 0 deletions
diff --git a/firmware/common/errno.c b/firmware/common/errno.c new file mode 100644 index 0000000000..6e7bb62b51 --- /dev/null +++ b/firmware/common/errno.c | |||
@@ -0,0 +1 @@ | |||
int errno; | |||
diff --git a/firmware/common/errno.h b/firmware/common/errno.h new file mode 100644 index 0000000000..4162f6a9ed --- /dev/null +++ b/firmware/common/errno.h | |||
@@ -0,0 +1,134 @@ | |||
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 | #ifndef _SYS_ERRNO_H_ | ||
6 | |||
7 | extern int errno; | ||
8 | |||
9 | #define EPERM 1 /* Not super-user */ | ||
10 | #define ENOENT 2 /* No such file or directory */ | ||
11 | #define ESRCH 3 /* No such process */ | ||
12 | #define EINTR 4 /* Interrupted system call */ | ||
13 | #define EIO 5 /* I/O error */ | ||
14 | #define ENXIO 6 /* No such device or address */ | ||
15 | #define E2BIG 7 /* Arg list too long */ | ||
16 | #define ENOEXEC 8 /* Exec format error */ | ||
17 | #define EBADF 9 /* Bad file number */ | ||
18 | #define ECHILD 10 /* No children */ | ||
19 | #define EAGAIN 11 /* No more processes */ | ||
20 | #define ENOMEM 12 /* Not enough core */ | ||
21 | #define EACCES 13 /* Permission denied */ | ||
22 | #define EFAULT 14 /* Bad address */ | ||
23 | #define ENOTBLK 15 /* Block device required */ | ||
24 | #define EBUSY 16 /* Mount device busy */ | ||
25 | #define EEXIST 17 /* File exists */ | ||
26 | #define EXDEV 18 /* Cross-device link */ | ||
27 | #define ENODEV 19 /* No such device */ | ||
28 | #define ENOTDIR 20 /* Not a directory */ | ||
29 | #define EISDIR 21 /* Is a directory */ | ||
30 | #define EINVAL 22 /* Invalid argument */ | ||
31 | #define ENFILE 23 /* Too many open files in system */ | ||
32 | #define EMFILE 24 /* Too many open files */ | ||
33 | #define ENOTTY 25 /* Not a typewriter */ | ||
34 | #define ETXTBSY 26 /* Text file busy */ | ||
35 | #define EFBIG 27 /* File too large */ | ||
36 | #define ENOSPC 28 /* No space left on device */ | ||
37 | #define ESPIPE 29 /* Illegal seek */ | ||
38 | #define EROFS 30 /* Read only file system */ | ||
39 | #define EMLINK 31 /* Too many links */ | ||
40 | #define EPIPE 32 /* Broken pipe */ | ||
41 | #define EDOM 33 /* Math arg out of domain of func */ | ||
42 | #define ERANGE 34 /* Math result not representable */ | ||
43 | #define ENOMSG 35 /* No message of desired type */ | ||
44 | #define EIDRM 36 /* Identifier removed */ | ||
45 | #define ECHRNG 37 /* Channel number out of range */ | ||
46 | #define EL2NSYNC 38 /* Level 2 not synchronized */ | ||
47 | #define EL3HLT 39 /* Level 3 halted */ | ||
48 | #define EL3RST 40 /* Level 3 reset */ | ||
49 | #define ELNRNG 41 /* Link number out of range */ | ||
50 | #define EUNATCH 42 /* Protocol driver not attached */ | ||
51 | #define ENOCSI 43 /* No CSI structure available */ | ||
52 | #define EL2HLT 44 /* Level 2 halted */ | ||
53 | #define EDEADLK 45 /* Deadlock condition */ | ||
54 | #define ENOLCK 46 /* No record locks available */ | ||
55 | #define EBADE 50 /* Invalid exchange */ | ||
56 | #define EBADR 51 /* Invalid request descriptor */ | ||
57 | #define EXFULL 52 /* Exchange full */ | ||
58 | #define ENOANO 53 /* No anode */ | ||
59 | #define EBADRQC 54 /* Invalid request code */ | ||
60 | #define EBADSLT 55 /* Invalid slot */ | ||
61 | #define EDEADLOCK 56 /* File locking deadlock error */ | ||
62 | #define EBFONT 57 /* Bad font file fmt */ | ||
63 | #define ENOSTR 60 /* Device not a stream */ | ||
64 | #define ENODATA 61 /* No data (for no delay io) */ | ||
65 | #define ETIME 62 /* Timer expired */ | ||
66 | #define ENOSR 63 /* Out of streams resources */ | ||
67 | #define ENONET 64 /* Machine is not on the network */ | ||
68 | #define ENOPKG 65 /* Package not installed */ | ||
69 | #define EREMOTE 66 /* The object is remote */ | ||
70 | #define ENOLINK 67 /* The link has been severed */ | ||
71 | #define EADV 68 /* Advertise error */ | ||
72 | #define ESRMNT 69 /* Srmount error */ | ||
73 | #define ECOMM 70 /* Communication error on send */ | ||
74 | #define EPROTO 71 /* Protocol error */ | ||
75 | #define EMULTIHOP 74 /* Multihop attempted */ | ||
76 | #define ELBIN 75 /* Inode is remote (not really error) */ | ||
77 | #define EDOTDOT 76 /* Cross mount point (not really error) */ | ||
78 | #define EBADMSG 77 /* Trying to read unreadable message */ | ||
79 | #define ENOTUNIQ 80 /* Given log. name not unique */ | ||
80 | #define EBADFD 81 /* f.d. invalid for this operation */ | ||
81 | #define EREMCHG 82 /* Remote address changed */ | ||
82 | #define ELIBACC 83 /* Can't access a needed shared lib */ | ||
83 | #define ELIBBAD 84 /* Accessing a corrupted shared lib */ | ||
84 | #define ELIBSCN 85 /* .lib section in a.out corrupted */ | ||
85 | #define ELIBMAX 86 /* Attempting to link in too many libs */ | ||
86 | #define ELIBEXEC 87 /* Attempting to exec a shared library */ | ||
87 | #define ENOSYS 88 /* Function not implemented */ | ||
88 | #define ENMFILE 89 /* No more files */ | ||
89 | #define ENOTEMPTY 90 /* Directory not empty */ | ||
90 | #define ENAMETOOLONG 91 /* File or path name too long */ | ||
91 | #define ELOOP 92 /* Too many symbolic links */ | ||
92 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ | ||
93 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ | ||
94 | #define ECONNRESET 104 /* Connection reset by peer */ | ||
95 | #define ENOBUFS 105 /* No buffer space available */ | ||
96 | #define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ | ||
97 | #define EPROTOTYPE 107 /* Protocol wrong type for socket */ | ||
98 | #define ENOTSOCK 108 /* Socket operation on non-socket */ | ||
99 | #define ENOPROTOOPT 109 /* Protocol not available */ | ||
100 | #define ESHUTDOWN 110 /* Can't send after socket shutdown */ | ||
101 | #define ECONNREFUSED 111 /* Connection refused */ | ||
102 | #define EADDRINUSE 112 /* Address already in use */ | ||
103 | #define ECONNABORTED 113 /* Connection aborted */ | ||
104 | #define ENETUNREACH 114 /* Network is unreachable */ | ||
105 | #define ENETDOWN 115 /* Network interface is not configured */ | ||
106 | #define ETIMEDOUT 116 /* Connection timed out */ | ||
107 | #define EHOSTDOWN 117 /* Host is down */ | ||
108 | #define EHOSTUNREACH 118 /* Host is unreachable */ | ||
109 | #define EINPROGRESS 119 /* Connection already in progress */ | ||
110 | #define EALREADY 120 /* Socket already connected */ | ||
111 | #define EDESTADDRREQ 121 /* Destination address required */ | ||
112 | #define EMSGSIZE 122 /* Message too long */ | ||
113 | #define EPROTONOSUPPORT 123 /* Unknown protocol */ | ||
114 | #define ESOCKTNOSUPPORT 124 /* Socket type not supported */ | ||
115 | #define EADDRNOTAVAIL 125 /* Address not available */ | ||
116 | #define ENETRESET 126 | ||
117 | #define EISCONN 127 /* Socket is already connected */ | ||
118 | #define ENOTCONN 128 /* Socket is not connected */ | ||
119 | #define ETOOMANYREFS 129 | ||
120 | #define EPROCLIM 130 | ||
121 | #define EUSERS 131 | ||
122 | #define EDQUOT 132 | ||
123 | #define ESTALE 133 | ||
124 | #define ENOTSUP 134 /* Not supported */ | ||
125 | #define ENOMEDIUM 135 /* No medium (in tape drive) */ | ||
126 | #define ENOSHARE 136 /* No such host or network path */ | ||
127 | #define ECASECLASH 137 /* Filename exists with different case */ | ||
128 | |||
129 | /* From cygwin32. */ | ||
130 | #define EWOULDBLOCK EAGAIN /* Operation would block */ | ||
131 | |||
132 | #define __ELASTERROR 2000 /* Users can add values starting here */ | ||
133 | |||
134 | #endif /* _SYS_ERRNO_H */ | ||
diff --git a/firmware/common/memcpy.c b/firmware/common/memcpy.c new file mode 100644 index 0000000000..5336f25a91 --- /dev/null +++ b/firmware/common/memcpy.c | |||
@@ -0,0 +1,111 @@ | |||
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 <_ansi.h> | ||
36 | #include <stddef.h> | ||
37 | #include <limits.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 | /* Threshhold 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) | ||
57 | { | ||
58 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
59 | char *dst = (char *) dst0; | ||
60 | char *src = (char *) src0; | ||
61 | |||
62 | _PTR save = dst0; | ||
63 | |||
64 | while (len0--) | ||
65 | { | ||
66 | *dst++ = *src++; | ||
67 | } | ||
68 | |||
69 | return save; | ||
70 | #else | ||
71 | char *dst = dst0; | ||
72 | _CONST char *src = src0; | ||
73 | long *aligned_dst; | ||
74 | _CONST long *aligned_src; | ||
75 | int len = len0; | ||
76 | |||
77 | /* If the size is small, or either SRC or DST is unaligned, | ||
78 | then punt into the byte copy loop. This should be rare. */ | ||
79 | if (!TOO_SMALL(len) && !UNALIGNED (src, dst)) | ||
80 | { | ||
81 | aligned_dst = (long*)dst; | ||
82 | aligned_src = (long*)src; | ||
83 | |||
84 | /* Copy 4X long words at a time if possible. */ | ||
85 | while (len >= BIGBLOCKSIZE) | ||
86 | { | ||
87 | *aligned_dst++ = *aligned_src++; | ||
88 | *aligned_dst++ = *aligned_src++; | ||
89 | *aligned_dst++ = *aligned_src++; | ||
90 | *aligned_dst++ = *aligned_src++; | ||
91 | len -= BIGBLOCKSIZE; | ||
92 | } | ||
93 | |||
94 | /* Copy one long word at a time if possible. */ | ||
95 | while (len >= LITTLEBLOCKSIZE) | ||
96 | { | ||
97 | *aligned_dst++ = *aligned_src++; | ||
98 | len -= LITTLEBLOCKSIZE; | ||
99 | } | ||
100 | |||
101 | /* Pick up any residual with a byte copier. */ | ||
102 | dst = (char*)aligned_dst; | ||
103 | src = (char*)aligned_src; | ||
104 | } | ||
105 | |||
106 | while (len--) | ||
107 | *dst++ = *src++; | ||
108 | |||
109 | return dst0; | ||
110 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
111 | } | ||
diff --git a/firmware/common/memset.c b/firmware/common/memset.c new file mode 100644 index 0000000000..a5890c8847 --- /dev/null +++ b/firmware/common/memset.c | |||
@@ -0,0 +1,109 @@ | |||
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 | |||
38 | #define LBLOCKSIZE (sizeof(long)) | ||
39 | #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) | ||
40 | #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) | ||
41 | |||
42 | _PTR | ||
43 | _DEFUN (memset, (m, c, n), | ||
44 | _PTR m _AND | ||
45 | int c _AND | ||
46 | size_t n) | ||
47 | { | ||
48 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
49 | char *s = (char *) m; | ||
50 | |||
51 | while (n-- != 0) | ||
52 | { | ||
53 | *s++ = (char) c; | ||
54 | } | ||
55 | |||
56 | return m; | ||
57 | #else | ||
58 | char *s = (char *) m; | ||
59 | int i; | ||
60 | unsigned long buffer; | ||
61 | unsigned long *aligned_addr; | ||
62 | |||
63 | if (!TOO_SMALL (n) && !UNALIGNED (m)) | ||
64 | { | ||
65 | /* If we get this far, we know that n is large and m is word-aligned. */ | ||
66 | |||
67 | aligned_addr = (unsigned long*)m; | ||
68 | |||
69 | /* Store C into each char sized location in BUFFER so that | ||
70 | we can set large blocks quickly. */ | ||
71 | c &= 0xff; | ||
72 | if (LBLOCKSIZE == 4) | ||
73 | { | ||
74 | buffer = (c << 8) | c; | ||
75 | buffer |= (buffer << 16); | ||
76 | } | ||
77 | else | ||
78 | { | ||
79 | buffer = 0; | ||
80 | for (i = 0; i < LBLOCKSIZE; i++) | ||
81 | buffer = (buffer << 8) | c; | ||
82 | } | ||
83 | |||
84 | while (n >= LBLOCKSIZE*4) | ||
85 | { | ||
86 | *aligned_addr++ = buffer; | ||
87 | *aligned_addr++ = buffer; | ||
88 | *aligned_addr++ = buffer; | ||
89 | *aligned_addr++ = buffer; | ||
90 | n -= 4*LBLOCKSIZE; | ||
91 | } | ||
92 | |||
93 | while (n >= LBLOCKSIZE) | ||
94 | { | ||
95 | *aligned_addr++ = buffer; | ||
96 | n -= LBLOCKSIZE; | ||
97 | } | ||
98 | /* Pick up the remainder with a bytewise loop. */ | ||
99 | s = (char*)aligned_addr; | ||
100 | } | ||
101 | |||
102 | while (n--) | ||
103 | { | ||
104 | *s++ = (char)c; | ||
105 | } | ||
106 | |||
107 | return m; | ||
108 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
109 | } | ||
diff --git a/firmware/common/qsort.c b/firmware/common/qsort.c new file mode 100644 index 0000000000..d47f470999 --- /dev/null +++ b/firmware/common/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 (*)())); | ||
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)()) | ||
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)()) | ||
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(pd - pc, pn - pd - es); | ||
212 | vecswap(pb, pn - r, r); | ||
213 | if ((r = pb - pa) > es) | ||
214 | qsort(a, r / es, es, cmp); | ||
215 | if ((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/common/strchr.c b/firmware/common/strchr.c new file mode 100644 index 0000000000..de4585f758 --- /dev/null +++ b/firmware/common/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/common/strcmp.c b/firmware/common/strcmp.c new file mode 100644 index 0000000000..81d65272ec --- /dev/null +++ b/firmware/common/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/common/strcpy.c b/firmware/common/strcpy.c new file mode 100644 index 0000000000..3dc3c33f60 --- /dev/null +++ b/firmware/common/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/common/strlen.c b/firmware/common/strlen.c new file mode 100644 index 0000000000..4249e14c78 --- /dev/null +++ b/firmware/common/strlen.c | |||
@@ -0,0 +1,88 @@ | |||
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 <_ansi.h> | ||
35 | #include <string.h> | ||
36 | #include <limits.h> | ||
37 | |||
38 | #define LBLOCKSIZE (sizeof (long)) | ||
39 | #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) | ||
40 | |||
41 | #if LONG_MAX == 2147483647L | ||
42 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
43 | #else | ||
44 | #if LONG_MAX == 9223372036854775807L | ||
45 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
46 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
47 | #else | ||
48 | #error long int is not a 32bit or 64bit type. | ||
49 | #endif | ||
50 | #endif | ||
51 | |||
52 | #ifndef DETECTNULL | ||
53 | #error long int is not a 32bit or 64bit byte | ||
54 | #endif | ||
55 | |||
56 | size_t | ||
57 | _DEFUN (strlen, (str), | ||
58 | _CONST char *str) | ||
59 | { | ||
60 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
61 | _CONST char *start = str; | ||
62 | |||
63 | while (*str) | ||
64 | str++; | ||
65 | |||
66 | return str - start; | ||
67 | #else | ||
68 | _CONST char *start = str; | ||
69 | unsigned long *aligned_addr; | ||
70 | |||
71 | if (!UNALIGNED (str)) | ||
72 | { | ||
73 | /* If the string is word-aligned, we can check for the presence of | ||
74 | a null in each word-sized block. */ | ||
75 | aligned_addr = (unsigned long*)str; | ||
76 | while (!DETECTNULL (*aligned_addr)) | ||
77 | aligned_addr++; | ||
78 | |||
79 | /* Once a null is detected, we check each byte in that block for a | ||
80 | precise position of the null. */ | ||
81 | str = (char*)aligned_addr; | ||
82 | } | ||
83 | |||
84 | while (*str) | ||
85 | str++; | ||
86 | return str - start; | ||
87 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
88 | } | ||
diff --git a/firmware/common/strncmp.c b/firmware/common/strncmp.c new file mode 100644 index 0000000000..9801b7d924 --- /dev/null +++ b/firmware/common/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/common/strncpy.c b/firmware/common/strncpy.c new file mode 100644 index 0000000000..7c1973ba66 --- /dev/null +++ b/firmware/common/strncpy.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | FUNCTION | ||
3 | <<strncpy>>---counted copy string | ||
4 | |||
5 | INDEX | ||
6 | strncpy | ||
7 | |||
8 | ANSI_SYNOPSIS | ||
9 | #include <string.h> | ||
10 | char *strncpy(char *<[dst]>, const char *<[src]>, size_t <[length]>); | ||
11 | |||
12 | TRAD_SYNOPSIS | ||
13 | #include <string.h> | ||
14 | char *strncpy(<[dst]>, <[src]>, <[length]>) | ||
15 | char *<[dst]>; | ||
16 | char *<[src]>; | ||
17 | size_t <[length]>; | ||
18 | |||
19 | DESCRIPTION | ||
20 | <<strncpy>> copies not more than <[length]> characters from the | ||
21 | the string pointed to by <[src]> (including the terminating | ||
22 | null character) to the array pointed to by <[dst]>. If the | ||
23 | string pointed to by <[src]> is shorter than <[length]> | ||
24 | characters, null characters are appended to the destination | ||
25 | array until a total of <[length]> characters have been | ||
26 | written. | ||
27 | |||
28 | RETURNS | ||
29 | This function returns the initial value of <[dst]>. | ||
30 | |||
31 | PORTABILITY | ||
32 | <<strncpy>> is ANSI C. | ||
33 | |||
34 | <<strncpy>> requires no supporting OS subroutines. | ||
35 | |||
36 | QUICKREF | ||
37 | strncpy ansi pure | ||
38 | */ | ||
39 | |||
40 | #include <string.h> | ||
41 | #include <limits.h> | ||
42 | |||
43 | /*SUPPRESS 560*/ | ||
44 | /*SUPPRESS 530*/ | ||
45 | |||
46 | /* Nonzero if either X or Y is not aligned on a "long" boundary. */ | ||
47 | #define UNALIGNED(X, Y) \ | ||
48 | (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) | ||
49 | |||
50 | #if LONG_MAX == 2147483647L | ||
51 | #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) | ||
52 | #else | ||
53 | #if LONG_MAX == 9223372036854775807L | ||
54 | /* Nonzero if X (a long int) contains a NULL byte. */ | ||
55 | #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) | ||
56 | #else | ||
57 | #error long int is not a 32bit or 64bit type. | ||
58 | #endif | ||
59 | #endif | ||
60 | |||
61 | #ifndef DETECTNULL | ||
62 | #error long int is not a 32bit or 64bit byte | ||
63 | #endif | ||
64 | |||
65 | #define TOO_SMALL(LEN) ((LEN) < sizeof (long)) | ||
66 | |||
67 | char * | ||
68 | _DEFUN (strncpy, (dst0, src0), | ||
69 | char *dst0 _AND | ||
70 | _CONST char *src0 _AND | ||
71 | size_t count) | ||
72 | { | ||
73 | #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) | ||
74 | char *dscan; | ||
75 | _CONST char *sscan; | ||
76 | |||
77 | dscan = dst0; | ||
78 | sscan = src0; | ||
79 | while (count > 0) | ||
80 | { | ||
81 | --count; | ||
82 | if ((*dscan++ = *sscan++) == '\0') | ||
83 | break; | ||
84 | } | ||
85 | while (count-- > 0) | ||
86 | *dscan++ = '\0'; | ||
87 | |||
88 | return dst0; | ||
89 | #else | ||
90 | char *dst = dst0; | ||
91 | _CONST char *src = src0; | ||
92 | long *aligned_dst; | ||
93 | _CONST long *aligned_src; | ||
94 | |||
95 | /* If SRC and DEST is aligned and count large enough, then copy words. */ | ||
96 | if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) | ||
97 | { | ||
98 | aligned_dst = (long*)dst; | ||
99 | aligned_src = (long*)src; | ||
100 | |||
101 | /* SRC and DEST are both "long int" aligned, try to do "long int" | ||
102 | sized copies. */ | ||
103 | while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) | ||
104 | { | ||
105 | count -= sizeof (long int); | ||
106 | *aligned_dst++ = *aligned_src++; | ||
107 | } | ||
108 | |||
109 | dst = (char*)aligned_dst; | ||
110 | src = (char*)aligned_src; | ||
111 | } | ||
112 | |||
113 | while (count > 0) | ||
114 | { | ||
115 | --count; | ||
116 | if ((*dst++ = *src++) == '\0') | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | while (count-- > 0) | ||
121 | *dst++ = '\0'; | ||
122 | |||
123 | return dst0; | ||
124 | #endif /* not PREFER_SIZE_OVER_SPEED */ | ||
125 | } | ||
diff --git a/firmware/common/strrchr.c b/firmware/common/strrchr.c new file mode 100644 index 0000000000..4f903afe2b --- /dev/null +++ b/firmware/common/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 | } | ||