litex: reorganize things, first work working version
[litex.git] / litex / soc / software / libbase / libc.c
1 /*
2 * MiSoC
3 * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
4 * Copyright (C) Linus Torvalds and 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 <ctype.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <limits.h>
25
26 /**
27 * strchr - Find the first occurrence of a character in a string
28 * @s: The string to be searched
29 * @c: The character to search for
30 */
31 char *strchr(const char *s, int c)
32 {
33 for (; *s != (char)c; ++s)
34 if (*s == '\0')
35 return NULL;
36 return (char *)s;
37 }
38
39 /**
40 * strpbrk - Find the first occurrence of a set of characters
41 * @cs: The string to be searched
42 * @ct: The characters to search for
43 */
44 char *strpbrk(const char *cs, const char *ct)
45 {
46 const char *sc1, *sc2;
47
48 for (sc1 = cs; *sc1 != '\0'; ++sc1) {
49 for (sc2 = ct; *sc2 != '\0'; ++sc2) {
50 if (*sc1 == *sc2)
51 return (char *)sc1;
52 }
53 }
54 return NULL;
55 }
56
57 /**
58 * strrchr - Find the last occurrence of a character in a string
59 * @s: The string to be searched
60 * @c: The character to search for
61 */
62 char *strrchr(const char *s, int c)
63 {
64 const char *p = s + strlen(s);
65 do {
66 if (*p == (char)c)
67 return (char *)p;
68 } while (--p >= s);
69 return NULL;
70 }
71
72 /**
73 * strnchr - Find a character in a length limited string
74 * @s: The string to be searched
75 * @count: The number of characters to be searched
76 * @c: The character to search for
77 */
78 char *strnchr(const char *s, size_t count, int c)
79 {
80 for (; count-- && *s != '\0'; ++s)
81 if (*s == (char)c)
82 return (char *)s;
83 return NULL;
84 }
85
86 /**
87 * strcpy - Copy a %NUL terminated string
88 * @dest: Where to copy the string to
89 * @src: Where to copy the string from
90 */
91 char *strcpy(char *dest, const char *src)
92 {
93 char *tmp = dest;
94
95 while ((*dest++ = *src++) != '\0')
96 /* nothing */;
97 return tmp;
98 }
99
100 /**
101 * strncpy - Copy a length-limited, %NUL-terminated string
102 * @dest: Where to copy the string to
103 * @src: Where to copy the string from
104 * @count: The maximum number of bytes to copy
105 *
106 * The result is not %NUL-terminated if the source exceeds
107 * @count bytes.
108 *
109 * In the case where the length of @src is less than that of
110 * count, the remainder of @dest will be padded with %NUL.
111 *
112 */
113 char *strncpy(char *dest, const char *src, size_t count)
114 {
115 char *tmp = dest;
116
117 while (count) {
118 if ((*tmp = *src) != 0)
119 src++;
120 tmp++;
121 count--;
122 }
123 return dest;
124 }
125
126 /**
127 * strcmp - Compare two strings
128 * @cs: One string
129 * @ct: Another string
130 */
131 int strcmp(const char *cs, const char *ct)
132 {
133 signed char __res;
134
135 while (1) {
136 if ((__res = *cs - *ct++) != 0 || !*cs++)
137 break;
138 }
139 return __res;
140 }
141
142 /**
143 * strncmp - Compare two strings using the first characters only
144 * @cs: One string
145 * @ct: Another string
146 * @count: Number of characters
147 */
148 int strncmp(const char *cs, const char *ct, size_t count)
149 {
150 signed char __res;
151 size_t n;
152
153 n = 0;
154 __res = 0;
155 while (n < count) {
156 if ((__res = *cs - *ct++) != 0 || !*cs++)
157 break;
158 n++;
159 }
160 return __res;
161 }
162
163 /**
164 * strcat - Append one %NUL-terminated string to another
165 * @dest: The string to be appended to
166 * @src: The string to append to it
167 */
168 char *strcat(char *dest, const char *src)
169 {
170 char *tmp = dest;
171
172 while (*dest)
173 dest++;
174 while ((*dest++ = *src++) != '\0')
175 ;
176 return tmp;
177 }
178
179 /**
180 * strncat - Append a length-limited, %NUL-terminated string to another
181 * @dest: The string to be appended to
182 * @src: The string to append to it
183 * @count: The maximum numbers of bytes to copy
184 *
185 * Note that in contrast to strncpy(), strncat() ensures the result is
186 * terminated.
187 */
188 char *strncat(char *dest, const char *src, size_t count)
189 {
190 char *tmp = dest;
191
192 if (count) {
193 while (*dest)
194 dest++;
195 while ((*dest++ = *src++) != 0) {
196 if (--count == 0) {
197 *dest = '\0';
198 break;
199 }
200 }
201 }
202 return tmp;
203 }
204
205 /**
206 * strlen - Find the length of a string
207 * @s: The string to be sized
208 */
209 size_t strlen(const char *s)
210 {
211 const char *sc;
212
213 for (sc = s; *sc != '\0'; ++sc)
214 /* nothing */;
215 return sc - s;
216 }
217
218 /**
219 * strnlen - Find the length of a length-limited string
220 * @s: The string to be sized
221 * @count: The maximum number of bytes to search
222 */
223 size_t strnlen(const char *s, size_t count)
224 {
225 const char *sc;
226
227 for (sc = s; count-- && *sc != '\0'; ++sc)
228 /* nothing */;
229 return sc - s;
230 }
231
232 /**
233 * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
234 * @s: The string to be searched
235 * @accept: The string to search for
236 */
237 size_t strspn(const char *s, const char *accept)
238 {
239 const char *p;
240 const char *a;
241 size_t count = 0;
242
243 for (p = s; *p != '\0'; ++p) {
244 for (a = accept; *a != '\0'; ++a) {
245 if (*p == *a)
246 break;
247 }
248 if (*a == '\0')
249 return count;
250 ++count;
251 }
252 return count;
253 }
254
255 /**
256 * memcmp - Compare two areas of memory
257 * @cs: One area of memory
258 * @ct: Another area of memory
259 * @count: The size of the area.
260 */
261 int memcmp(const void *cs, const void *ct, size_t count)
262 {
263 const unsigned char *su1, *su2;
264 int res = 0;
265
266 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
267 if ((res = *su1 - *su2) != 0)
268 break;
269 return res;
270 }
271
272 /**
273 * memset - Fill a region of memory with the given value
274 * @s: Pointer to the start of the area.
275 * @c: The byte to fill the area with
276 * @count: The size of the area.
277 */
278 void *memset(void *s, int c, size_t count)
279 {
280 char *xs = s;
281
282 while (count--)
283 *xs++ = c;
284 return s;
285 }
286
287 /**
288 * memcpy - Copies one area of memory to another
289 * @dest: Destination
290 * @src: Source
291 * @n: The size to copy.
292 */
293 void *memcpy(void *to, const void *from, size_t n)
294 {
295 void *xto = to;
296 size_t temp;
297
298 if(!n)
299 return xto;
300 if((long)to & 1) {
301 char *cto = to;
302 const char *cfrom = from;
303 *cto++ = *cfrom++;
304 to = cto;
305 from = cfrom;
306 n--;
307 }
308 if((long)from & 1) {
309 char *cto = to;
310 const char *cfrom = from;
311 for (; n; n--)
312 *cto++ = *cfrom++;
313 return xto;
314 }
315 if(n > 2 && (long)to & 2) {
316 short *sto = to;
317 const short *sfrom = from;
318 *sto++ = *sfrom++;
319 to = sto;
320 from = sfrom;
321 n -= 2;
322 }
323 if((long)from & 2) {
324 short *sto = to;
325 const short *sfrom = from;
326 temp = n >> 1;
327 for (; temp; temp--)
328 *sto++ = *sfrom++;
329 to = sto;
330 from = sfrom;
331 if(n & 1) {
332 char *cto = to;
333 const char *cfrom = from;
334 *cto = *cfrom;
335 }
336 return xto;
337 }
338 temp = n >> 2;
339 if(temp) {
340 long *lto = to;
341 const long *lfrom = from;
342 for(; temp; temp--)
343 *lto++ = *lfrom++;
344 to = lto;
345 from = lfrom;
346 }
347 if(n & 2) {
348 short *sto = to;
349 const short *sfrom = from;
350 *sto++ = *sfrom++;
351 to = sto;
352 from = sfrom;
353 }
354 if(n & 1) {
355 char *cto = to;
356 const char *cfrom = from;
357 *cto = *cfrom;
358 }
359 return xto;
360 }
361
362 /**
363 * memmove - Copies one area of memory to another, overlap possible
364 * @dest: Destination
365 * @src: Source
366 * @n: The size to copy.
367 */
368 void *memmove(void *dest, const void *src, size_t count)
369 {
370 char *tmp, *s;
371
372 if(dest <= src) {
373 tmp = (char *) dest;
374 s = (char *) src;
375 while(count--)
376 *tmp++ = *s++;
377 } else {
378 tmp = (char *)dest + count;
379 s = (char *)src + count;
380 while(count--)
381 *--tmp = *--s;
382 }
383
384 return dest;
385 }
386
387 /**
388 * strstr - Find the first substring in a %NUL terminated string
389 * @s1: The string to be searched
390 * @s2: The string to search for
391 */
392 char *strstr(const char *s1, const char *s2)
393 {
394 size_t l1, l2;
395
396 l2 = strlen(s2);
397 if (!l2)
398 return (char *)s1;
399 l1 = strlen(s1);
400 while (l1 >= l2) {
401 l1--;
402 if (!memcmp(s1, s2, l2))
403 return (char *)s1;
404 s1++;
405 }
406 return NULL;
407 }
408
409 /**
410 * memchr - Find a character in an area of memory.
411 * @s: The memory area
412 * @c: The byte to search for
413 * @n: The size of the area.
414 *
415 * returns the address of the first occurrence of @c, or %NULL
416 * if @c is not found
417 */
418 void *memchr(const void *s, int c, size_t n)
419 {
420 const unsigned char *p = s;
421 while (n-- != 0) {
422 if ((unsigned char)c == *p++) {
423 return (void *)(p - 1);
424 }
425 }
426 return NULL;
427 }
428
429 /**
430 * strtoul - convert a string to an unsigned long
431 * @nptr: The start of the string
432 * @endptr: A pointer to the end of the parsed string will be placed here
433 * @base: The number base to use
434 */
435 unsigned long strtoul(const char *nptr, char **endptr, int base)
436 {
437 unsigned long result = 0,value;
438
439 if (!base) {
440 base = 10;
441 if (*nptr == '0') {
442 base = 8;
443 nptr++;
444 if ((toupper(*nptr) == 'X') && isxdigit(nptr[1])) {
445 nptr++;
446 base = 16;
447 }
448 }
449 } else if (base == 16) {
450 if (nptr[0] == '0' && toupper(nptr[1]) == 'X')
451 nptr += 2;
452 }
453 while (isxdigit(*nptr) &&
454 (value = isdigit(*nptr) ? *nptr-'0' : toupper(*nptr)-'A'+10) < base) {
455 result = result*base + value;
456 nptr++;
457 }
458 if (endptr)
459 *endptr = (char *)nptr;
460 return result;
461 }
462
463 /**
464 * strtol - convert a string to a signed long
465 * @nptr: The start of the string
466 * @endptr: A pointer to the end of the parsed string will be placed here
467 * @base: The number base to use
468 */
469 long strtol(const char *nptr, char **endptr, int base)
470 {
471 if(*nptr=='-')
472 return -strtoul(nptr+1,endptr,base);
473 return strtoul(nptr,endptr,base);
474 }
475
476 int skip_atoi(const char **s)
477 {
478 int i=0;
479
480 while (isdigit(**s))
481 i = i*10 + *((*s)++) - '0';
482 return i;
483 }
484
485 char *number(char *buf, char *end, unsigned long num, int base, int size, int precision, int type)
486 {
487 char c,sign,tmp[66];
488 const char *digits;
489 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
490 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
491 int i;
492
493 digits = (type & PRINTF_LARGE) ? large_digits : small_digits;
494 if (type & PRINTF_LEFT)
495 type &= ~PRINTF_ZEROPAD;
496 if (base < 2 || base > 36)
497 return NULL;
498 c = (type & PRINTF_ZEROPAD) ? '0' : ' ';
499 sign = 0;
500 if (type & PRINTF_SIGN) {
501 if ((signed long) num < 0) {
502 sign = '-';
503 num = - (signed long) num;
504 size--;
505 } else if (type & PRINTF_PLUS) {
506 sign = '+';
507 size--;
508 } else if (type & PRINTF_SPACE) {
509 sign = ' ';
510 size--;
511 }
512 }
513 if (type & PRINTF_SPECIAL) {
514 if (base == 16)
515 size -= 2;
516 else if (base == 8)
517 size--;
518 }
519 i = 0;
520 if (num == 0)
521 tmp[i++]='0';
522 else while (num != 0) {
523 tmp[i++] = digits[num % base];
524 num = num / base;
525 }
526 if (i > precision)
527 precision = i;
528 size -= precision;
529 if (!(type&(PRINTF_ZEROPAD+PRINTF_LEFT))) {
530 while(size-->0) {
531 if (buf < end)
532 *buf = ' ';
533 ++buf;
534 }
535 }
536 if (sign) {
537 if (buf < end)
538 *buf = sign;
539 ++buf;
540 }
541 if (type & PRINTF_SPECIAL) {
542 if (base==8) {
543 if (buf < end)
544 *buf = '0';
545 ++buf;
546 } else if (base==16) {
547 if (buf < end)
548 *buf = '0';
549 ++buf;
550 if (buf < end)
551 *buf = digits[33];
552 ++buf;
553 }
554 }
555 if (!(type & PRINTF_LEFT)) {
556 while (size-- > 0) {
557 if (buf < end)
558 *buf = c;
559 ++buf;
560 }
561 }
562 while (i < precision--) {
563 if (buf < end)
564 *buf = '0';
565 ++buf;
566 }
567 while (i-- > 0) {
568 if (buf < end)
569 *buf = tmp[i];
570 ++buf;
571 }
572 while (size-- > 0) {
573 if (buf < end)
574 *buf = ' ';
575 ++buf;
576 }
577 return buf;
578 }
579
580 /**
581 * vscnprintf - Format a string and place it in a buffer
582 * @buf: The buffer to place the result into
583 * @size: The size of the buffer, including the trailing null space
584 * @fmt: The format string to use
585 * @args: Arguments for the format string
586 *
587 * The return value is the number of characters which have been written into
588 * the @buf not including the trailing '\0'. If @size is <= 0 the function
589 * returns 0.
590 *
591 * Call this function if you are already dealing with a va_list.
592 * You probably want scnprintf() instead.
593 */
594 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
595 {
596 int i;
597
598 i=vsnprintf(buf,size,fmt,args);
599 return (i >= size) ? (size - 1) : i;
600 }
601
602
603 /**
604 * snprintf - Format a string and place it in a buffer
605 * @buf: The buffer to place the result into
606 * @size: The size of the buffer, including the trailing null space
607 * @fmt: The format string to use
608 * @...: Arguments for the format string
609 *
610 * The return value is the number of characters which would be
611 * generated for the given input, excluding the trailing null,
612 * as per ISO C99. If the return is greater than or equal to
613 * @size, the resulting string is truncated.
614 */
615 int snprintf(char * buf, size_t size, const char *fmt, ...)
616 {
617 va_list args;
618 int i;
619
620 va_start(args, fmt);
621 i=vsnprintf(buf,size,fmt,args);
622 va_end(args);
623 return i;
624 }
625
626 /**
627 * scnprintf - Format a string and place it in a buffer
628 * @buf: The buffer to place the result into
629 * @size: The size of the buffer, including the trailing null space
630 * @fmt: The format string to use
631 * @...: Arguments for the format string
632 *
633 * The return value is the number of characters written into @buf not including
634 * the trailing '\0'. If @size is <= 0 the function returns 0.
635 */
636
637 int scnprintf(char * buf, size_t size, const char *fmt, ...)
638 {
639 va_list args;
640 int i;
641
642 va_start(args, fmt);
643 i = vsnprintf(buf, size, fmt, args);
644 va_end(args);
645 return (i >= size) ? (size - 1) : i;
646 }
647
648 /**
649 * vsprintf - Format a string and place it in a buffer
650 * @buf: The buffer to place the result into
651 * @fmt: The format string to use
652 * @args: Arguments for the format string
653 *
654 * The function returns the number of characters written
655 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
656 * buffer overflows.
657 *
658 * Call this function if you are already dealing with a va_list.
659 * You probably want sprintf() instead.
660 */
661 int vsprintf(char *buf, const char *fmt, va_list args)
662 {
663 return vsnprintf(buf, INT_MAX, fmt, args);
664 }
665
666 /**
667 * sprintf - Format a string and place it in a buffer
668 * @buf: The buffer to place the result into
669 * @fmt: The format string to use
670 * @...: Arguments for the format string
671 *
672 * The function returns the number of characters written
673 * into @buf. Use snprintf() or scnprintf() in order to avoid
674 * buffer overflows.
675 */
676 int sprintf(char * buf, const char *fmt, ...)
677 {
678 va_list args;
679 int i;
680
681 va_start(args, fmt);
682 i=vsnprintf(buf, INT_MAX, fmt, args);
683 va_end(args);
684 return i;
685 }
686
687 /* From linux/lib/ctype.c, Copyright (C) 1991, 1992 Linus Torvalds */
688 const unsigned char _ctype[] = {
689 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
690 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
691 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
692 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
693 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
694 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
695 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
696 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
697 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
698 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
699 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
700 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
701 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
702 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
703 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
704 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
705 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
706 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
707 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
708 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
709 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
710 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
711 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
712 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
713
714 /**
715 * rand - Returns a pseudo random number
716 */
717
718 static unsigned int randseed;
719 unsigned int rand(void)
720 {
721 randseed = 129 * randseed + 907633385;
722 return randseed;
723 }
724
725 void srand(unsigned int seed)
726 {
727 randseed = seed;
728 }
729
730 void abort(void)
731 {
732 printf("Aborted.");
733 while(1);
734 }