GNU compliant library naming
[mw/milkymist.git] / software / libbase / libc.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4  * Copyright (C) Linux kernel developers
5  * 
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 3 of the License.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <libc.h>
20
21 /**
22  * strchr - Find the first occurrence of a character in a string
23  * @s: The string to be searched
24  * @c: The character to search for
25  */
26 char *strchr(const char *s, int c)
27 {
28         for (; *s != (char)c; ++s)
29                 if (*s == '\0')
30                         return NULL;
31         return (char *)s;
32 }
33
34 /**
35  * strrchr - Find the last occurrence of a character in a string
36  * @s: The string to be searched
37  * @c: The character to search for
38  */
39 char *strrchr(const char *s, int c)
40 {
41        const char *p = s + strlen(s);
42        do {
43            if (*p == (char)c)
44                return (char *)p;
45        } while (--p >= s);
46        return NULL;
47 }
48
49 /**
50  * strnchr - Find a character in a length limited string
51  * @s: The string to be searched
52  * @count: The number of characters to be searched
53  * @c: The character to search for
54  */
55 char *strnchr(const char *s, size_t count, int c)
56 {
57         for (; count-- && *s != '\0'; ++s)
58                 if (*s == (char)c)
59                         return (char *)s;
60         return NULL;
61 }
62
63 /**
64  * strcpy - Copy a %NUL terminated string
65  * @dest: Where to copy the string to
66  * @src: Where to copy the string from
67  */
68 char *strcpy(char *dest, const char *src)
69 {
70         char *tmp = dest;
71
72         while ((*dest++ = *src++) != '\0')
73                 /* nothing */;
74         return tmp;
75 }
76
77 /**
78  * strncpy - Copy a length-limited, %NUL-terminated string
79  * @dest: Where to copy the string to
80  * @src: Where to copy the string from
81  * @count: The maximum number of bytes to copy
82  *
83  * The result is not %NUL-terminated if the source exceeds
84  * @count bytes.
85  *
86  * In the case where the length of @src is less than  that  of
87  * count, the remainder of @dest will be padded with %NUL.
88  *
89  */
90 char *strncpy(char *dest, const char *src, size_t count)
91 {
92         char *tmp = dest;
93         
94         while (count) {
95                 if ((*tmp = *src) != 0)
96                         src++;
97                 tmp++;
98                 count--;
99         }
100         return dest;
101 }
102
103 /**
104  * strcmp - Compare two strings
105  * @cs: One string
106  * @ct: Another string
107  */
108 int strcmp(const char *cs, const char *ct)
109 {
110         signed char __res;
111
112         while (1) {
113                 if ((__res = *cs - *ct++) != 0 || !*cs++)
114                         break;
115         }
116         return __res;
117 }
118
119 /**
120  * strncmp - Compare two strings using the first characters only
121  * @cs: One string
122  * @ct: Another string
123  * @count: Number of characters
124  */
125 int strncmp(const char *cs, const char *ct, size_t count)
126 {
127         signed char __res;
128         size_t n;
129
130         n = 0;
131         __res = 0;
132         while (n < count) {
133                 if ((__res = *cs - *ct++) != 0 || !*cs++)
134                         break;
135                 n++;
136         }
137         return __res;
138 }
139
140 /**
141  * strlen - Find the length of a string
142  * @s: The string to be sized
143  */
144 size_t strlen(const char *s)
145 {
146         const char *sc;
147
148         for (sc = s; *sc != '\0'; ++sc)
149                 /* nothing */;
150         return sc - s;
151 }
152
153 /**
154  * strnlen - Find the length of a length-limited string
155  * @s: The string to be sized
156  * @count: The maximum number of bytes to search
157  */
158 size_t strnlen(const char *s, size_t count)
159 {
160         const char *sc;
161
162         for (sc = s; count-- && *sc != '\0'; ++sc)
163                 /* nothing */;
164         return sc - s;
165 }
166
167 /**
168  * memcmp - Compare two areas of memory
169  * @cs: One area of memory
170  * @ct: Another area of memory
171  * @count: The size of the area.
172  */
173 int memcmp(const void *cs, const void *ct, size_t count)
174 {
175         const unsigned char *su1, *su2;
176         int res = 0;
177
178         for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
179                 if ((res = *su1 - *su2) != 0)
180                         break;
181         return res;
182 }
183
184 /**
185  * memset - Fill a region of memory with the given value
186  * @s: Pointer to the start of the area.
187  * @c: The byte to fill the area with
188  * @count: The size of the area.
189  */
190 void *memset(void *s, int c, size_t count)
191 {
192         char *xs = s;
193
194         while (count--)
195                 *xs++ = c;
196         return s;
197 }
198
199 /**
200  * memcpy - Copies one area of memory to another
201  * @dest: Destination
202  * @src: Source
203  * @n: The size to copy.
204  */
205 void *memcpy(void *dest, const void *src, size_t n)
206 {
207         char *_dest = (char *)dest;
208         char *_src = (char *)src;
209         size_t i;
210
211         for(i=0;i<n;i++)
212                 _dest[i] = _src[i];
213
214         return dest;
215 }
216
217 /**
218  * memmove - Copies one area of memory to another, overlap possible
219  * @dest: Destination
220  * @src: Source
221  * @n: The size to copy.
222  */
223 void *memmove(void *dest, const void *src, size_t count)
224 {
225         char *tmp, *s;
226
227         if(dest <= src) {
228                 tmp = (char *) dest;
229                 s = (char *) src;
230                 while(count--)
231                         *tmp++ = *s++;
232         } else {
233                 tmp = (char *)dest + count;
234                 s = (char *)src + count;
235                 while(count--)
236                         *--tmp = *--s;
237         }
238
239         return dest;
240 }
241
242
243 /**
244  * strtoul - convert a string to an unsigned long
245  * @nptr: The start of the string
246  * @endptr: A pointer to the end of the parsed string will be placed here
247  * @base: The number base to use
248  */
249 unsigned long strtoul(const char *nptr, char **endptr, int base)
250 {
251         unsigned long result = 0,value;
252
253         if (!base) {
254                 base = 10;
255                 if (*nptr == '0') {
256                         base = 8;
257                         nptr++;
258                         if ((toupper(*nptr) == 'X') && isxdigit(nptr[1])) {
259                                 nptr++;
260                                 base = 16;
261                         }
262                 }
263         } else if (base == 16) {
264                 if (nptr[0] == '0' && toupper(nptr[1]) == 'X')
265                         nptr += 2;
266         }
267         while (isxdigit(*nptr) &&
268                (value = isdigit(*nptr) ? *nptr-'0' : toupper(*nptr)-'A'+10) < base) {
269                 result = result*base + value;
270                 nptr++;
271         }
272         if (endptr)
273                 *endptr = (char *)nptr;
274         return result;
275 }
276
277 /**
278  * strtol - convert a string to a signed long
279  * @nptr: The start of the string
280  * @endptr: A pointer to the end of the parsed string will be placed here
281  * @base: The number base to use
282  */
283 long strtol(const char *nptr, char **endptr, int base)
284 {
285         if(*nptr=='-')
286                 return -strtoul(nptr+1,endptr,base);
287         return strtoul(nptr,endptr,base);
288 }
289
290 int skip_atoi(const char **s)
291 {
292         int i=0;
293
294         while (isdigit(**s))
295                 i = i*10 + *((*s)++) - '0';
296         return i;
297 }
298
299 char *number(char *buf, char *end, unsigned long num, int base, int size, int precision, int type)
300 {
301         char c,sign,tmp[66];
302         const char *digits;
303         static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
304         static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
305         int i;
306
307         digits = (type & PRINTF_LARGE) ? large_digits : small_digits;
308         if (type & PRINTF_LEFT)
309                 type &= ~PRINTF_ZEROPAD;
310         if (base < 2 || base > 36)
311                 return NULL;
312         c = (type & PRINTF_ZEROPAD) ? '0' : ' ';
313         sign = 0;
314         if (type & PRINTF_SIGN) {
315                 if ((signed long) num < 0) {
316                         sign = '-';
317                         num = - (signed long) num;
318                         size--;
319                 } else if (type & PRINTF_PLUS) {
320                         sign = '+';
321                         size--;
322                 } else if (type & PRINTF_SPACE) {
323                         sign = ' ';
324                         size--;
325                 }
326         }
327         if (type & PRINTF_SPECIAL) {
328                 if (base == 16)
329                         size -= 2;
330                 else if (base == 8)
331                         size--;
332         }
333         i = 0;
334         if (num == 0)
335                 tmp[i++]='0';
336         else while (num != 0) {
337                 tmp[i++] = digits[num % base];
338                 num = num / base;
339         }
340         if (i > precision)
341                 precision = i;
342         size -= precision;
343         if (!(type&(PRINTF_ZEROPAD+PRINTF_LEFT))) {
344                 while(size-->0) {
345                         if (buf < end)
346                                 *buf = ' ';
347                         ++buf;
348                 }
349         }
350         if (sign) {
351                 if (buf < end)
352                         *buf = sign;
353                 ++buf;
354         }
355         if (type & PRINTF_SPECIAL) {
356                 if (base==8) {
357                         if (buf < end)
358                                 *buf = '0';
359                         ++buf;
360                 } else if (base==16) {
361                         if (buf < end)
362                                 *buf = '0';
363                         ++buf;
364                         if (buf < end)
365                                 *buf = digits[33];
366                         ++buf;
367                 }
368         }
369         if (!(type & PRINTF_LEFT)) {
370                 while (size-- > 0) {
371                         if (buf < end)
372                                 *buf = c;
373                         ++buf;
374                 }
375         }
376         while (i < precision--) {
377                 if (buf < end)
378                         *buf = '0';
379                 ++buf;
380         }
381         while (i-- > 0) {
382                 if (buf < end)
383                         *buf = tmp[i];
384                 ++buf;
385         }
386         while (size-- > 0) {
387                 if (buf < end)
388                         *buf = ' ';
389                 ++buf;
390         }
391         return buf;
392 }
393
394 /**
395  * vscnprintf - Format a string and place it in a buffer
396  * @buf: The buffer to place the result into
397  * @size: The size of the buffer, including the trailing null space
398  * @fmt: The format string to use
399  * @args: Arguments for the format string
400  *
401  * The return value is the number of characters which have been written into
402  * the @buf not including the trailing '\0'. If @size is <= 0 the function
403  * returns 0.
404  *
405  * Call this function if you are already dealing with a va_list.
406  * You probably want scnprintf() instead.
407  */
408 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
409 {
410         int i;
411
412         i=vsnprintf(buf,size,fmt,args);
413         return (i >= size) ? (size - 1) : i;
414 }
415
416
417 /**
418  * snprintf - Format a string and place it in a buffer
419  * @buf: The buffer to place the result into
420  * @size: The size of the buffer, including the trailing null space
421  * @fmt: The format string to use
422  * @...: Arguments for the format string
423  *
424  * The return value is the number of characters which would be
425  * generated for the given input, excluding the trailing null,
426  * as per ISO C99.  If the return is greater than or equal to
427  * @size, the resulting string is truncated.
428  */
429 int snprintf(char * buf, size_t size, const char *fmt, ...)
430 {
431         va_list args;
432         int i;
433
434         va_start(args, fmt);
435         i=vsnprintf(buf,size,fmt,args);
436         va_end(args);
437         return i;
438 }
439
440 /**
441  * scnprintf - Format a string and place it in a buffer
442  * @buf: The buffer to place the result into
443  * @size: The size of the buffer, including the trailing null space
444  * @fmt: The format string to use
445  * @...: Arguments for the format string
446  *
447  * The return value is the number of characters written into @buf not including
448  * the trailing '\0'. If @size is <= 0 the function returns 0.
449  */
450
451 int scnprintf(char * buf, size_t size, const char *fmt, ...)
452 {
453         va_list args;
454         int i;
455
456         va_start(args, fmt);
457         i = vsnprintf(buf, size, fmt, args);
458         va_end(args);
459         return (i >= size) ? (size - 1) : i;
460 }
461
462 /**
463  * vsprintf - Format a string and place it in a buffer
464  * @buf: The buffer to place the result into
465  * @fmt: The format string to use
466  * @args: Arguments for the format string
467  *
468  * The function returns the number of characters written
469  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
470  * buffer overflows.
471  *
472  * Call this function if you are already dealing with a va_list.
473  * You probably want sprintf() instead.
474  */
475 int vsprintf(char *buf, const char *fmt, va_list args)
476 {
477         return vsnprintf(buf, INT_MAX, fmt, args);
478 }
479
480 /**
481  * sprintf - Format a string and place it in a buffer
482  * @buf: The buffer to place the result into
483  * @fmt: The format string to use
484  * @...: Arguments for the format string
485  *
486  * The function returns the number of characters written
487  * into @buf. Use snprintf() or scnprintf() in order to avoid
488  * buffer overflows.
489  */
490 int sprintf(char * buf, const char *fmt, ...)
491 {
492         va_list args;
493         int i;
494
495         va_start(args, fmt);
496         i=vsnprintf(buf, INT_MAX, fmt, args);
497         va_end(args);
498         return i;
499 }
500
501 /**
502  * rand - Returns a pseudo random number
503  */
504
505 static unsigned int seed;
506 unsigned int rand()
507 {
508         seed = 129 * seed + 907633385;
509         return seed;
510 }