Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src-rt / shared / bcmstdlib.c
blobe58a2c5a2739d0d4c9b600f6fa5983a9700e9812
1 /*
2 * stdlib support routines for self-contained images.
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: bcmstdlib.c,v 1.51.20.1 2010-03-23 01:20:17 Exp $
22 * bcmstdlib.c file should be used only to construct an OSL or alone without any OSL
23 * It should not be used with any orbitarary OSL's as there could be a conflict
24 * with some of the routines defined here.
27 #include <typedefs.h>
28 #if defined(NDIS) || defined(_MINOSL_) || defined(__vxworks) || defined(PCBIOS) || \
29 defined(EFI)
30 /* debatable */
31 #include <osl.h>
32 #elif 1
33 #include <stdio.h>
34 #endif
37 * Define BCMSTDLIB_WIN32_APP if this is a Win32 Application compile
39 #if defined(_WIN32) && !defined(NDIS) && !defined(EFI)
40 #define BCMSTDLIB_WIN32_APP 1
41 #endif /* _WIN32 && !NDIS */
44 * Define BCMSTDLIB_SNPRINTF_ONLY if we only want snprintf & vsnprintf implementations
46 #if (defined(_WIN32) && !defined(EFI)) || defined(__vxworks) || defined(_CFE_)
47 #define BCMSTDLIB_SNPRINTF_ONLY 1
48 #endif
50 #include <stdarg.h>
51 #include <bcmstdlib.h>
52 #ifndef BCMSTDLIB_WIN32_APP
53 #include <bcmutils.h>
54 #endif
56 #ifdef MSGTRACE
57 #include <msgtrace.h>
58 #endif
60 #ifdef BCMSTDLIB_WIN32_APP
62 /* for a WIN32 application, use _vsnprintf as basis of vsnprintf/snprintf to
63 * support full set of format specifications.
66 int
67 vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap)
69 int r;
71 r = _vsnprintf(buf, bufsize, fmt, ap);
73 /* Microsoft _vsnprintf() will not null terminate on overflow,
74 * so null terminate at buffer end on error
76 if (r < 0 && bufsize > 0)
77 buf[bufsize - 1] = '\0';
79 return r;
82 int
83 snprintf(char *buf, size_t bufsize, const char *fmt, ...)
85 va_list ap;
86 int r;
88 va_start(ap, fmt);
89 r = vsnprintf(buf, bufsize, fmt, ap);
90 va_end(ap);
92 return r;
95 #else /* BCMSTDLIB_WIN32_APP */
98 static const char digits[17] = "0123456789ABCDEF";
99 static const char ldigits[17] = "0123456789abcdef";
101 static int
102 __atox(char *buf, char * end, unsigned int num, unsigned int radix, int width,
103 const char *digits)
105 char buffer[16];
106 char *op;
107 int retval;
109 op = &buffer[0];
110 retval = 0;
112 do {
113 *op++ = digits[num % radix];
114 retval++;
115 num /= radix;
116 } while (num != 0);
118 if (width && (width > retval)) {
119 width = width - retval;
120 while (width) {
121 *op++ = '0';
122 retval++;
123 width--;
127 while (op != buffer) {
128 op--;
129 if (buf <= end)
130 *buf = *op;
131 buf++;
134 return retval;
138 BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap)
140 char *optr;
141 char *end;
142 const char *iptr;
143 unsigned char *tmpptr;
144 unsigned int x;
145 int i;
146 int leadingzero;
147 int leadingnegsign;
148 int islong;
149 int width;
150 int width2 = 0;
151 int hashash = 0;
153 optr = buf;
154 end = buf + size - 1;
155 iptr = fmt;
157 if (end < buf - 1) {
158 end = ((void *) -1);
159 size = end - buf + 1;
162 while (*iptr) {
163 if (*iptr != '%') {
164 if (optr <= end)
165 *optr = *iptr;
166 ++optr;
167 ++iptr;
168 continue;
171 iptr++;
173 if (*iptr == '#') {
174 hashash = 1;
175 iptr++;
177 if (*iptr == '-') {
178 leadingnegsign = 1;
179 iptr++;
180 } else
181 leadingnegsign = 0;
183 if (*iptr == '0')
184 leadingzero = 1;
185 else
186 leadingzero = 0;
188 width = 0;
189 while (*iptr && bcm_isdigit(*iptr)) {
190 width += (*iptr - '0');
191 iptr++;
192 if (bcm_isdigit(*iptr))
193 width *= 10;
195 if (*iptr == '.') {
196 iptr++;
197 width2 = 0;
198 while (*iptr && bcm_isdigit(*iptr)) {
199 width2 += (*iptr - '0');
200 iptr++;
201 if (bcm_isdigit(*iptr)) width2 *= 10;
205 islong = 0;
206 if (*iptr == 'l') {
207 islong++;
208 iptr++;
211 switch (*iptr) {
212 case 's':
213 tmpptr = (unsigned char *) va_arg(ap, unsigned char *);
214 if (!tmpptr) tmpptr = (unsigned char *) "(null)";
215 if ((width == 0) & (width2 == 0)) {
216 while (*tmpptr) {
217 if (optr <= end)
218 *optr = *tmpptr;
219 ++optr;
220 ++tmpptr;
222 break;
224 while (width && *tmpptr) {
225 if (optr <= end)
226 *optr = *tmpptr;
227 ++optr;
228 ++tmpptr;
229 width--;
231 while (width) {
232 if (optr <= end)
233 *optr = ' ';
234 ++optr;
235 width--;
237 break;
238 case 'd':
239 case 'i':
240 i = va_arg(ap, int);
241 if (i < 0) {
242 if (optr <= end)
243 *optr = '-';
244 ++optr;
245 i = -i;
247 optr += __atox(optr, end, i, 10, width, digits);
248 break;
249 case 'u':
250 x = va_arg(ap, unsigned int);
251 optr += __atox(optr, end, x, 10, width, digits);
252 break;
253 case 'X':
254 case 'x':
255 x = va_arg(ap, unsigned int);
256 optr += __atox(optr, end, x, 16, width,
257 (*iptr == 'X') ? digits : ldigits);
258 break;
259 case 'p':
260 case 'P':
261 x = va_arg(ap, unsigned int);
262 optr += __atox(optr, end, x, 16, 8,
263 (*iptr == 'P') ? digits : ldigits);
264 break;
265 case 'c':
266 x = va_arg(ap, int);
267 if (optr <= end)
268 *optr = x & 0xff;
269 optr++;
270 break;
272 default:
273 if (optr <= end)
274 *optr = *iptr;
275 optr++;
276 break;
278 iptr++;
281 if (optr <= end) {
282 *optr = '\0';
283 return (int)(optr - buf);
284 } else {
285 *end = '\0';
286 return (int)(end - buf);
292 BCMROMFN(snprintf)(char *buf, size_t bufsize, const char *fmt, ...)
294 va_list ap;
295 int r;
297 va_start(ap, fmt);
298 r = vsnprintf(buf, bufsize, fmt, ap);
299 va_end(ap);
301 return r;
304 #endif /* BCMSTDLIB_WIN32_APP */
306 #ifndef BCMSTDLIB_SNPRINTF_ONLY
310 BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap)
312 return (vsnprintf(buf, INT_MAX, fmt, ap));
317 BCMROMFN(sprintf)(char *buf, const char *fmt, ...)
319 va_list ap;
320 int count;
322 va_start(ap, fmt);
323 count = vsprintf(buf, fmt, ap);
324 va_end(ap);
326 return count;
330 void *
331 BCMROMFN(memmove)(void *dest, const void *src, size_t n)
333 /* only use memcpy if there is no overlap. otherwise copy each byte in a safe sequence */
334 if (((const char *)src >= (char *)dest + n) || ((const char *)src + n <= (char *)dest)) {
335 return memcpy(dest, src, n);
338 /* Overlapping copy forward or backward */
339 if (src < dest) {
340 unsigned char *d = (unsigned char *)dest + (n - 1);
341 const unsigned char *s = (const unsigned char *)src + (n - 1);
342 while (n) {
343 *d-- = *s--;
344 n--;
346 } else if (src > dest) {
347 unsigned char *d = (unsigned char *)dest;
348 const unsigned char *s = (const unsigned char *)src;
349 while (n) {
350 *d++ = *s++;
351 n--;
355 return dest;
358 #ifndef EFI
360 BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n)
362 const unsigned char *ss1;
363 const unsigned char *ss2;
365 ss1 = (const unsigned char *)s1;
366 ss2 = (const unsigned char *)s2;
368 while (n) {
369 if (*ss1 < *ss2)
370 return -1;
371 if (*ss1 > *ss2)
372 return 1;
373 ss1++;
374 ss2++;
375 n--;
378 return 0;
381 /* Skip over functions that are being used from DriverLibrary to save space */
382 char *
383 BCMROMFN(strcpy)(char *dest, const char *src)
385 char *ptr = dest;
387 while ((*ptr++ = *src++) != '\0')
390 return dest;
393 char *
394 BCMROMFN(strncpy)(char *dest, const char *src, size_t n)
396 char *endp;
397 char *p;
399 p = dest;
400 endp = p + n;
402 while (p != endp && (*p++ = *src++) != '\0')
405 /* zero fill remainder */
406 while (p != endp)
407 *p++ = '\0';
409 return dest;
412 size_t
413 BCMROMFN(strlen)(const char *s)
415 size_t n = 0;
417 while (*s) {
418 s++;
419 n++;
422 return n;
426 BCMROMFN(strcmp)(const char *s1, const char *s2)
428 while (*s2 && *s1) {
429 if (*s1 < *s2)
430 return -1;
431 if (*s1 > *s2)
432 return 1;
433 s1++;
434 s2++;
437 if (*s1 && !*s2)
438 return 1;
439 if (!*s1 && *s2)
440 return -1;
441 return 0;
443 #endif /* EFI */
446 BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n)
448 while (*s2 && *s1 && n) {
449 if (*s1 < *s2)
450 return -1;
451 if (*s1 > *s2)
452 return 1;
453 s1++;
454 s2++;
455 n--;
458 if (!n)
459 return 0;
460 if (*s1 && !*s2)
461 return 1;
462 if (!*s1 && *s2)
463 return -1;
464 return 0;
467 char *
468 BCMROMFN(strchr)(const char *str, int c)
470 char *x = (char *)str;
472 while (*x != (char)c) {
473 if (*x++ == '\0')
474 return (NULL);
476 return (x);
479 char *
480 BCMROMFN(strrchr)(const char *str, int c)
482 char *save = NULL;
484 do {
485 if (*str == (char) c)
486 save = (char*)(str);
487 } while (*str++ != '\0');
489 return (save);
492 /* Skip over functions that are being used from DriverLibrary to save space */
493 #ifndef EFI
494 char *
495 BCMROMFN(strcat)(char *d, const char *s)
497 strcpy(&d[strlen(d)], s);
498 return (d);
500 #endif /* EFI */
502 char *
503 BCMROMFN(index)(const char *s, int c)
505 /* Terminating NUL is considered part of string */
507 for (; *s != c; s++)
508 if (!*s)
509 return NULL;
511 return (char *)s;
514 /* Skip over functions that are being used from DriverLibrary to save space */
515 #ifndef EFI
516 char *
517 BCMROMFN(strstr)(const char *s, const char *substr)
519 int substr_len = strlen(substr);
521 for (; *s; s++)
522 if (strncmp(s, substr, substr_len) == 0)
523 return (char *)s;
525 return NULL;
527 #endif /* EFI */
529 size_t
530 BCMROMFN(strspn)(const char *s, const char *accept)
532 uint count = 0;
534 while (s[count] && index(accept, s[count]))
535 count++;
537 return count;
540 size_t
541 BCMROMFN(strcspn)(const char *s, const char *reject)
543 uint count = 0;
545 while (s[count] && !index(reject, s[count]))
546 count++;
548 return count;
551 void *
552 BCMROMFN(memchr)(const void *s, int c, size_t n)
554 if (n != 0) {
555 const unsigned char *ptr = s;
557 do {
558 if (*ptr == (unsigned char)c)
559 return (void *)ptr;
560 ptr++;
561 n--;
562 } while (n != 0);
564 return NULL;
567 unsigned long
568 BCMROMFN(strtoul)(const char *cp, char **endp, int base)
570 ulong result, value;
571 bool minus;
573 minus = FALSE;
575 while (bcm_isspace(*cp))
576 cp++;
578 if (cp[0] == '+')
579 cp++;
580 else if (cp[0] == '-') {
581 minus = TRUE;
582 cp++;
585 if (base == 0) {
586 if (cp[0] == '0') {
587 if ((cp[1] == 'x') || (cp[1] == 'X')) {
588 base = 16;
589 cp = &cp[2];
590 } else {
591 base = 8;
592 cp = &cp[1];
594 } else
595 base = 10;
596 } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
597 cp = &cp[2];
600 result = 0;
602 while (bcm_isxdigit(*cp) &&
603 (value = bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) <
604 (ulong) base) {
605 result = result * base + value;
606 cp++;
609 if (minus)
610 result = (ulong)(result * -1);
612 if (endp)
613 *endp = (char *)cp;
615 return (result);
618 #ifndef EFI
619 /* memset is not in ROM offload because it is used directly by the compiler in
620 * structure assignments/character array initialization with "".
622 void *
623 memset(void *dest, int c, size_t n)
625 uint32 w, *dw;
626 unsigned char *d;
629 dw = (uint32 *)dest;
631 /* 8 min because we have to create w */
632 if ((n >= 8) && (((uintptr)dest & 3) == 0)) {
633 if (c == 0)
634 w = 0;
635 else {
636 unsigned char ch;
638 ch = (unsigned char)(c & 0xff);
639 w = (ch << 8) | ch;
640 w |= w << 16;
642 while (n >= 4) {
643 *dw++ = w;
644 n -= 4;
647 d = (unsigned char *)dw;
649 while (n) {
650 *d++ = (unsigned char)c;
651 n--;
654 return d;
657 /* memcpy is not in ROM offload because it is used directly by the compiler in
658 * structure assignments.
660 void *
661 memcpy(void *dest, const void *src, size_t n)
663 uint32 *dw;
664 const uint32 *sw;
665 unsigned char *d;
666 const unsigned char *s;
668 sw = (const uint32 *)src;
669 dw = (uint32 *)dest;
670 if ((n >= 4) && (((uintptr)src & 3) == 0) && (((uintptr)dest & 3) == 0)) {
671 while (n >= 4) {
672 *dw++ = *sw++;
673 n -= 4;
676 d = (unsigned char *)dw;
677 s = (const unsigned char *)sw;
678 while (n) {
679 *d++ = *s++;
680 n--;
683 return dest;
685 #endif /* EFI */
687 /* Include printf if it has already not been defined as NULL */
688 #ifndef printf
690 printf(const char *fmt, ...)
692 va_list ap;
693 int count, i;
694 char buffer[PRINTF_BUFLEN + 1];
696 va_start(ap, fmt);
697 count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
698 va_end(ap);
700 for (i = 0; i < count; i++) {
701 putc(buffer[i]);
703 #ifdef EFI
704 if (buffer[i] == '\n')
705 putc('\r');
706 #endif
709 #ifdef MSGTRACE
710 msgtrace_put(buffer, count);
711 #endif
713 return count;
715 #endif /* printf */
718 #if !defined(_WIN32) && !defined(_CFE_) && !defined(EFI)
720 fputs(const char *s, FILE *stream /* UNUSED */)
722 char c;
723 while ((c = *s++))
724 putchar(c);
725 return 0;
729 puts(const char *s)
731 fputs(s, stdout);
732 putchar('\n');
733 return 0;
737 fputc(int c, FILE *stream /* UNUSED */)
739 putc(c);
740 return (int)(unsigned char)c;
744 unsigned long
745 rand(void)
747 static unsigned long seed = 1;
748 long x, hi, lo, t;
750 x = seed;
751 hi = x / 127773;
752 lo = x % 127773;
753 t = 16807 * lo - 2836 * hi;
754 if (t <= 0) t += 0x7fffffff;
755 seed = t;
756 return t;
758 #endif
759 #endif /* BCMSTDLIB_SNPRINTF_ONLY */