source: mainline/libc/generic/string.c@ ce5bcb4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ce5bcb4 was 7f079d9, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Tetris now works on mips on gxemul on both console & framebuffer.
It doesn't work in msim, but it seems to be msim bug this time.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (C) 2005 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string.h>
30#include <unistd.h>
31#include <ctype.h>
32#include <limits.h>
33#include <align.h>
34
35
36/* Dummy implementation of mem/ functions */
37
38void * memset(void *s, int c, size_t n)
39{
40 char *os = s;
41 while (n--)
42 *(os++) = c;
43 return s;
44}
45
46struct along {unsigned long n; } __attribute__ ((packed));
47
48static void * unaligned_memcpy(void *dst, const void *src, size_t n)
49{
50 int i, j;
51 struct along *adst = dst;
52 const struct along *asrc = src;
53
54 for (i = 0; i < n/sizeof(unsigned long); i++)
55 adst[i].n = asrc[i].n;
56
57 for (j = 0; j < n%sizeof(unsigned long); j++)
58 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
59
60 return (char *)src;
61}
62
63void * memcpy(void *dst, const void *src, size_t n)
64{
65 int i, j;
66
67 if (((long)dst & (sizeof(long)-1)) || ((long)src & (sizeof(long)-1)))
68 return unaligned_memcpy(dst, src, n);
69
70 for (i = 0; i < n/sizeof(unsigned long); i++)
71 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
72
73 for (j = 0; j < n%sizeof(unsigned long); j++)
74 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
75
76 return (char *)src;
77}
78
79void * memmove(void *dst, const void *src, size_t n)
80{
81 int i, j;
82
83 if (src > dst)
84 return memcpy(dst, src, n);
85
86 for (j = (n%sizeof(unsigned long))-1; j >= 0; j--)
87 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
88
89 for (i = n/sizeof(unsigned long)-1; i >=0 ; i--)
90 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
91
92 return (char *)src;
93}
94
95
96/** Count the number of characters in the string, not including terminating 0.
97 * @param str string
98 * @return number of characters in string.
99 */
100size_t strlen(const char *str)
101{
102 size_t counter = 0;
103
104 while (str[counter] != 0) {
105 counter++;
106 }
107
108 return counter;
109}
110
111int strcmp(const char *a,const char *b)
112{
113 int c=0;
114
115 while(a[c]&&b[c]&&(!(a[c]-b[c]))) c++;
116
117 return a[c]-b[c];
118
119}
120
121
122
123/** Return pointer to the first occurence of character c in string
124 * @param str scanned string
125 * @param c searched character (taken as one byte)
126 * @return pointer to the matched character or NULL if it is not found in given string.
127 */
128char *strchr(const char *str, int c)
129{
130 while (*str != '\0') {
131 if (*str == (char)c)
132 return (char *)str;
133 str++;
134 }
135
136 return NULL;
137}
138
139/** Return pointer to the last occurence of character c in string
140 * @param str scanned string
141 * @param c searched character (taken as one byte)
142 * @return pointer to the matched character or NULL if it is not found in given string.
143 */
144char *strrchr(const char *str, int c)
145{
146 char *retval = NULL;
147
148 while (*str != '\0') {
149 if (*str == (char)c)
150 retval = (char *)str;
151 str++;
152 }
153
154 return (char *)retval;
155}
156
157/** Convert string to a number.
158 * Core of strtol and strtoul functions.
159 * @param nptr pointer to string
160 * @param endptr if not NULL, function stores here pointer to the first invalid character
161 * @param base zero or number between 2 and 36 inclusive
162 * @param sgn its set to 1 if minus found
163 * @return result of conversion.
164 */
165static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
166{
167 unsigned char c;
168 unsigned long result = 0;
169 unsigned long a, b;
170 const char *str = nptr;
171 const char *tmpptr;
172
173 while (isspace(*str))
174 str++;
175
176 if (*str == '-') {
177 *sgn = 1;
178 ++str;
179 } else if (*str == '+')
180 ++str;
181
182 if (base) {
183 if ((base == 1) || (base > 36)) {
184 /* FIXME: set errno to EINVAL */
185 return 0;
186 }
187 if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
188 str += 2;
189 }
190 } else {
191 base = 10;
192
193 if (*str == '0') {
194 base = 8;
195 if ((str[1] == 'X') || (str[1] == 'x')) {
196 base = 16;
197 str += 2;
198 }
199 }
200 }
201
202 tmpptr = str;
203
204 while (*str) {
205 c = *str;
206 c = ( c >= 'a'? c-'a'+10:(c >= 'A'?c-'A'+10:(c <= '9'?c-'0':0xff)));
207 if (c > base) {
208 break;
209 }
210
211 a = (result & 0xff) * base + c;
212 b = (result >> 8) * base + (a >> 8);
213
214 if (b > (ULONG_MAX >> 8)) {
215 /* overflow */
216 /* FIXME: errno = ERANGE*/
217 return ULONG_MAX;
218 }
219
220 result = (b << 8) + (a & 0xff);
221 ++str;
222 }
223
224 if (str == tmpptr) {
225 /* no number was found => first invalid character is the first character of the string */
226 /* FIXME: set errno to EINVAL */
227 str = nptr;
228 result = 0;
229 }
230
231 if (endptr)
232 *endptr = (char *)str;
233
234 if (nptr == str) {
235 /*FIXME: errno = EINVAL*/
236 return 0;
237 }
238
239 return result;
240}
241
242/** Convert initial part of string to long int according to given base.
243 * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
244 * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
245 * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
246 * Otherwise the base 0 is taken as decimal.
247 * @param nptr pointer to string
248 * @param endptr if not NULL, function stores here pointer to the first invalid character
249 * @param base zero or number between 2 and 36 inclusive
250 * @return result of conversion.
251 */
252long int strtol(const char *nptr, char **endptr, int base)
253{
254 char sgn = 0;
255 unsigned long number = 0;
256
257 number = _strtoul(nptr, endptr, base, &sgn);
258
259 if (number > LONG_MAX) {
260 if ((sgn) && (number == (unsigned long)(LONG_MAX) + 1)) {
261 /* FIXME: set 0 to errno */
262 return number;
263 }
264 /* FIXME: set ERANGE to errno */
265 return (sgn?LONG_MIN:LONG_MAX);
266 }
267
268 return (sgn?-number:number);
269}
270
271
272/** Convert initial part of string to unsigned long according to given base.
273 * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
274 * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
275 * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
276 * Otherwise the base 0 is taken as decimal.
277 * @param nptr pointer to string
278 * @param endptr if not NULL, function stores here pointer to the first invalid character
279 * @param base zero or number between 2 and 36 inclusive
280 * @return result of conversion.
281 */
282unsigned long strtoul(const char *nptr, char **endptr, int base)
283{
284 char sgn = 0;
285 unsigned long number = 0;
286
287 number = _strtoul(nptr, endptr, base, &sgn);
288
289 return (sgn?-number:number);
290}
291
292char *strcpy(char *dest, const char *src)
293{
294 while (*(dest++) = *(src++))
295 ;
296}
297
298char *strncpy(char *dest, const char *src, size_t n)
299{
300 while ((*(dest++) = *(src++)) && --n)
301 ;
302}
Note: See TracBrowser for help on using the repository browser.