Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / shared / bcmstdlib.c
blob1cadc46d224da78e678e341a75099ce2d863d9ec
1 /*
2 * Initialization and support routines for self-booting
3 * compressed image.
5 * Copyright 2004, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
13 * $Id$
17 * bcmstdlib.c file should be used only to construct an OSL or alone without any OSL
18 * It should not be used with any orbitarary OSL's as there could be a conflict
19 * with some of the routines defined here.
22 #include <typedefs.h>
23 #if defined(NDIS) || defined(_MINOSL_) || defined(__vxworks) || \
24 defined(PCBIOS) || defined(LINUXSIM) || defined(EFI)
25 /* debatable */
26 #include <osl.h>
27 #elif !defined(__IOPOS__)
28 #include <stdio.h>
29 #endif
32 * Define BCMSTDLIB_WIN32_APP if this is a Win32 Application compile
34 #if defined(_WIN32) && !defined(NDIS) && !defined(EFI)
35 #define BCMSTDLIB_WIN32_APP 1
36 #endif /* _WIN32 && !NDIS */
39 * Define BCMSTDLIB_SNPRINTF_ONLY if we only want snprintf & vsnprintf implementations
41 #if (defined(_WIN32) && !defined(EFI)) || defined(__vxworks) || defined(_CFE_)
42 #define BCMSTDLIB_SNPRINTF_ONLY 1
43 #endif
45 #include <stdarg.h>
46 #include <bcmstdlib.h>
47 #ifndef BCMSTDLIB_WIN32_APP
48 #include <bcmutils.h>
49 #endif
51 #ifdef BCMSTDLIB_WIN32_APP
53 /* for a WIN32 application, use _vsnprintf as basis of vsnprintf/snprintf to
54 * support full set of format specifications.
57 int
58 vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap)
60 int r;
62 r = _vsnprintf(buf, bufsize, fmt, ap);
64 /* Microsoft _vsnprintf() will not null terminate on overflow,
65 * so null terminate at buffer end on error
67 if (r < 0 && bufsize > 0)
68 buf[bufsize - 1] = '\0';
70 return r;
73 int
74 snprintf(char *buf, size_t bufsize, const char *fmt, ...)
76 va_list ap;
77 int r;
79 va_start(ap, fmt);
80 r = vsnprintf(buf, bufsize, fmt, ap);
81 va_end(ap);
83 return r;
86 #else /* BCMSTDLIB_WIN32_APP */
88 #ifndef BCMROMOFFLOAD
90 static const char digits[17] = "0123456789ABCDEF";
91 static const char ldigits[17] = "0123456789abcdef";
93 static int
94 __atox(char *buf, char * end, unsigned int num, unsigned int radix, int width,
95 const char *digits)
97 char buffer[16];
98 char *op;
99 int retval;
101 op = &buffer[0];
102 retval = 0;
104 do {
105 *op++ = digits[num % radix];
106 retval++;
107 num /= radix;
108 } while (num != 0);
110 if (width && (width > retval)) {
111 width = width - retval;
112 while (width) {
113 *op++ = '0';
114 retval++;
115 width--;
119 while (op != buffer) {
120 op--;
121 if (buf <= end)
122 *buf = *op;
123 buf++;
126 return retval;
130 BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap)
132 char *optr;
133 char *end;
134 const char *iptr;
135 unsigned char *tmpptr;
136 unsigned int x;
137 int i;
138 int leadingzero;
139 int leadingnegsign;
140 int islong;
141 int width;
142 int width2 = 0;
143 int hashash = 0;
145 optr = buf;
146 end = buf + size - 1;
147 iptr = fmt;
149 if (end < buf - 1) {
150 end = ((void *) -1);
151 size = end - buf + 1;
154 while (*iptr) {
155 if (*iptr != '%') {
156 if (optr <= end)
157 *optr = *iptr;
158 ++optr;
159 ++iptr;
160 continue;
163 iptr++;
165 if (*iptr == '#') {
166 hashash = 1;
167 iptr++;
169 if (*iptr == '-') {
170 leadingnegsign = 1;
171 iptr++;
172 } else
173 leadingnegsign = 0;
175 if (*iptr == '0')
176 leadingzero = 1;
177 else
178 leadingzero = 0;
180 width = 0;
181 while (*iptr && bcm_isdigit(*iptr)) {
182 width += (*iptr - '0');
183 iptr++;
184 if (bcm_isdigit(*iptr))
185 width *= 10;
187 if (*iptr == '.') {
188 iptr++;
189 width2 = 0;
190 while (*iptr && bcm_isdigit(*iptr)) {
191 width2 += (*iptr - '0');
192 iptr++;
193 if (bcm_isdigit(*iptr)) width2 *= 10;
197 islong = 0;
198 if (*iptr == 'l') {
199 islong++;
200 iptr++;
203 switch (*iptr) {
204 case 's':
205 tmpptr = (unsigned char *) va_arg(ap, unsigned char *);
206 if (!tmpptr) tmpptr = (unsigned char *) "(null)";
207 if ((width == 0) & (width2 == 0)) {
208 while (*tmpptr) {
209 if (optr <= end)
210 *optr = *tmpptr;
211 ++optr;
212 ++tmpptr;
214 break;
216 while (width && *tmpptr) {
217 if (optr <= end)
218 *optr = *tmpptr;
219 ++optr;
220 ++tmpptr;
221 width--;
223 while (width) {
224 if (optr <= end)
225 *optr = ' ';
226 ++optr;
227 width--;
229 break;
230 case 'd':
231 case 'i':
232 i = va_arg(ap, int);
233 if (i < 0) {
234 if (optr <= end)
235 *optr = '-';
236 ++optr;
237 i = -i;
239 optr += __atox(optr, end, i, 10, width, digits);
240 break;
241 case 'u':
242 x = va_arg(ap, unsigned int);
243 optr += __atox(optr, end, x, 10, width, digits);
244 break;
245 case 'X':
246 case 'x':
247 x = va_arg(ap, unsigned int);
248 optr += __atox(optr, end, x, 16, width,
249 (*iptr == 'X') ? digits : ldigits);
250 break;
251 case 'p':
252 case 'P':
253 x = va_arg(ap, unsigned int);
254 optr += __atox(optr, end, x, 16, 8,
255 (*iptr == 'P') ? digits : ldigits);
256 break;
257 case 'c':
258 x = va_arg(ap, int);
259 if (optr <= end)
260 *optr = x & 0xff;
261 optr++;
262 break;
264 default:
265 if (optr <= end)
266 *optr = *iptr;
267 optr++;
268 break;
270 iptr++;
273 if (optr <= end) {
274 *optr = '\0';
275 return (int)(optr - buf);
276 } else {
277 *end = '\0';
278 return (int)(end - buf);
284 BCMROMFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...)
286 va_list ap;
287 int r;
289 va_start(ap, fmt);
290 r = vsnprintf(buf, bufsize, fmt, ap);
291 va_end(ap);
293 return r;
295 #endif /* !BCMROMOFFLOAD */
297 #endif /* BCMSTDLIB_WIN32_APP */
299 #ifndef BCMSTDLIB_SNPRINTF_ONLY
301 #ifndef BCMROMOFFLOAD
304 BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap)
306 return (vsnprintf(buf, INT_MAX, fmt, ap));
311 BCMROMFN(sprintf)(char *buf, const char *fmt, ...)
313 va_list ap;
314 int count;
316 va_start(ap, fmt);
317 count = vsprintf(buf, fmt, ap);
318 va_end(ap);
320 return count;
324 void *
325 BCMROMFN(memmove)(void *dest, const void *src, size_t n)
327 unsigned char *d;
328 const unsigned char *s;
330 /* only use memmove if dest is after source, otherwise use memcopy */
331 if (src < dest)
332 return memcpy(dest, src, n);
334 /* do what memcpy does, but starting at the end and work backwords */
335 d = (unsigned char *)dest + (n-1);
336 s = (const unsigned char *)src + (n-1);
338 while (n) {
339 *d-- = *s--;
340 n--;
343 return dest;
346 #ifndef EFI
348 BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n)
350 const unsigned char *ss1;
351 const unsigned char *ss2;
353 ss1 = (const unsigned char *)s1;
354 ss2 = (const unsigned char *)s2;
356 while (n) {
357 if (*ss1 < *ss2)
358 return -1;
359 if (*ss1 > *ss2)
360 return 1;
361 ss1++;
362 ss2++;
363 n--;
366 return 0;
369 /* Skip over functions that are being used from DriverLibrary to save space */
370 char *
371 BCMROMFN(strcpy)(char *dest, const char *src)
373 char *ptr = dest;
375 while ((*ptr++ = *src++) != '\0')
378 return dest;
381 char *
382 BCMROMFN(strncpy)(char *dest, const char *src, size_t n)
384 char *endp;
385 char *p;
387 p = dest;
388 endp = p + n;
390 while (p != endp && (*p++ = *src++) != '\0')
393 /* zero fill remainder */
394 while (p != endp)
395 *p++ = '\0';
397 return dest;
400 size_t
401 BCMROMFN(strlen)(const char *s)
403 size_t n = 0;
405 while (*s) {
406 s++;
407 n++;
410 return n;
414 BCMROMFN(strcmp)(const char *s1, const char *s2)
416 while (*s2 && *s1) {
417 if (*s1 < *s2)
418 return -1;
419 if (*s1 > *s2)
420 return 1;
421 s1++;
422 s2++;
425 if (*s1 && !*s2)
426 return 1;
427 if (!*s1 && *s2)
428 return -1;
429 return 0;
431 #endif /* EFI */
434 BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n)
436 while (*s2 && *s1 && n) {
437 if (*s1 < *s2)
438 return -1;
439 if (*s1 > *s2)
440 return 1;
441 s1++;
442 s2++;
443 n--;
446 if (!n)
447 return 0;
448 if (*s1 && !*s2)
449 return 1;
450 if (!*s1 && *s2)
451 return -1;
452 return 0;
455 char *
456 BCMROMFN(strchr)(const char *str, int c)
458 char *x = (char *)str;
460 while (*x != (char)c) {
461 if (*x++ == '\0')
462 return (NULL);
464 return (x);
467 char *
468 BCMROMFN(strrchr)(const char *str, int c)
470 char *save = NULL;
472 do {
473 if (*str == (char) c)
474 save = (char*)(str);
475 } while (*str++ != '\0');
477 return (save);
480 /* Skip over functions that are being used from DriverLibrary to save space */
481 #ifndef EFI
482 char *
483 BCMROMFN(strcat)(char *d, const char *s)
485 strcpy(&d[strlen(d)], s);
486 return (d);
488 #endif /* EFI */
490 char *
491 BCMROMFN(index)(const char *s, int c)
493 /* Terminating NUL is considered part of string */
495 for (; *s != c; s++)
496 if (!*s)
497 return NULL;
499 return (char *)s;
502 /* Skip over functions that are being used from DriverLibrary to save space */
503 #ifndef EFI
504 char *
505 BCMROMFN(strstr)(const char *s, const char *substr)
507 int substr_len = strlen(substr);
509 for (; *s; s++)
510 if (strncmp(s, substr, substr_len) == 0)
511 return (char *)s;
513 return NULL;
515 #endif /* EFI */
517 size_t
518 BCMROMFN(strspn)(const char *s, const char *accept)
520 uint count = 0;
522 while (s[count] && index(accept, s[count]))
523 count++;
525 return count;
528 size_t
529 BCMROMFN(strcspn)(const char *s, const char *reject)
531 uint count = 0;
533 while (s[count] && !index(reject, s[count]))
534 count++;
536 return count;
539 void *
540 BCMROMFN(memchr)(const void *s, int c, size_t n)
542 if (n != 0) {
543 const unsigned char *ptr = s;
545 do {
546 if (*ptr == (unsigned char)c)
547 return (void *)ptr;
548 ptr++;
549 n--;
550 } while (n != 0);
552 return NULL;
555 unsigned long
556 BCMROMFN(strtoul)(const char *cp, char **endp, int base)
558 ulong result, value;
559 bool minus;
561 minus = FALSE;
563 while (bcm_isspace(*cp))
564 cp++;
566 if (cp[0] == '+')
567 cp++;
568 else if (cp[0] == '-') {
569 minus = TRUE;
570 cp++;
573 if (base == 0) {
574 if (cp[0] == '0') {
575 if ((cp[1] == 'x') || (cp[1] == 'X')) {
576 base = 16;
577 cp = &cp[2];
578 } else {
579 base = 8;
580 cp = &cp[1];
582 } else
583 base = 10;
584 } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
585 cp = &cp[2];
588 result = 0;
590 while (bcm_isxdigit(*cp) &&
591 (value = bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) <
592 (ulong) base) {
593 result = result * base + value;
594 cp++;
597 if (minus)
598 result = (ulong)(result * -1);
600 if (endp)
601 *endp = (char *)cp;
603 return (result);
605 #endif /* !BCMROMOFFLOAD */
607 #ifndef EFI
608 /* memset is not in ROM offload because it is used directly by the compiler in
609 * structure assignments/character array initialization with "".
611 void *
612 memset(void *dest, int c, size_t n)
614 uint32 w, *dw;
615 unsigned char *d;
618 dw = (uint32 *)dest;
620 /* 8 min because we have to create w */
621 if ((n >= 8) && (((uint)dest & 3) == 0)) {
622 if (c == 0)
623 w = 0;
624 else {
625 unsigned char ch;
627 ch = (unsigned char)(c & 0xff);
628 w = (ch << 8) | ch;
629 w |= w << 16;
631 while (n >= 4) {
632 *dw++ = w;
633 n -= 4;
636 d = (unsigned char *)dw;
638 while (n) {
639 *d++ = (unsigned char)c;
640 n--;
643 return d;
646 /* memcpy is not in ROM offload because it is used directly by the compiler in
647 * structure assignments.
649 void *
650 memcpy(void *dest, const void *src, size_t n)
652 uint32 *dw;
653 const uint32 *sw;
654 unsigned char *d;
655 const unsigned char *s;
657 sw = (const uint32 *)src;
658 dw = (uint32 *)dest;
659 if ((n >= 4) && (((uint)src & 3) == 0) && (((uint)dest & 3) == 0)) {
660 while (n >= 4) {
661 *dw++ = *sw++;
662 n -= 4;
665 d = (unsigned char *)dw;
666 s = (const unsigned char *)sw;
667 while (n) {
668 *d++ = *s++;
669 n--;
672 return dest;
674 #endif /* EFI */
676 /* Include printf if it has already not been defined as NULL */
677 #ifndef printf
679 printf(const char *fmt, ...)
681 va_list ap;
682 int count, i;
683 char buffer[PRINTF_BUFLEN + 1];
685 va_start(ap, fmt);
686 count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
687 va_end(ap);
689 for (i = 0; i < count; i++) {
690 putc(buffer[i]);
692 #ifdef EFI
693 if (buffer[i] == '\n')
694 putc('\r');
695 #endif
698 return count;
700 #endif /* printf */
703 fputs(const char *s, FILE *stream /* UNUSED */)
705 char c;
706 while ((c = *s++))
707 putchar(c);
708 return 0;
712 puts(const char *s)
714 fputs(s, stdout);
715 putchar('\n');
716 return 0;
720 fputc(int c, FILE *stream /* UNUSED */)
722 putc(c);
723 return (int)(unsigned char)c;
727 unsigned long
728 rand(void)
730 static unsigned long seed = 1;
731 long x, hi, lo, t;
733 x = seed;
734 hi = x / 127773;
735 lo = x % 127773;
736 t = 16807 * lo - 2836 * hi;
737 if (t <= 0) t += 0x7fffffff;
738 seed = t;
739 return t;
741 #endif /* BCMSTDLIB_SNPRINTF_ONLY */