openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

libc.c (13711B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Some routines to avoid dependence on libc in the driver.  Define
      8  * RTOS_STRINGS if your RTOS already has these routines, because the RTOS
      9  * implementations may be more efficient and save room.
     10  *
     11  * Note: ONLY libc routines needed by library code (drv or bcm) should
     12  * be here.  This file is not a general dumping-ground for all libc
     13  * routines needed by diagnostics, etc.
     14  */
     15 
     16 #include <sal/core/libc.h>
     17 #include <sal/core/alloc.h>
     18 
     19 #ifndef RTOS_STRINGS
     20 /* { */
     21 int 
     22 sal_strlen(const char *s)
     23 {
     24     const char *s_orig = s;
     25 
     26     while (*s != 0) {
     27 	s++;
     28     }
     29 
     30     return (s - s_orig);
     31 }
     32 
     33 char *
     34 sal_strcpy(char *dst, const char *src)
     35 {
     36     char *dst_orig = dst;
     37 
     38     while ((*dst++ = *src++) != 0)
     39 	;
     40 
     41     return dst_orig;
     42 }
     43 
     44 char *
     45 sal_strncpy(char *dst, const char *src, size_t length)
     46 {
     47   int i = 0;
     48   char *dst_orig = dst;
     49 
     50   while (i < length && (*dst++ = *src++) != 0) {
     51     ++i;
     52   }
     53 
     54   return dst_orig;
     55 }
     56 
     57 
     58 int 
     59 sal_strcmp(const char *s1, const char *s2)
     60 {
     61     do {
     62 	if (*s1 < *s2) {
     63 	    return -1;
     64 	} else if (*s1 > *s2) {
     65 	    return 1;
     66 	}
     67 	s1++;
     68     } while (*s2++);
     69 
     70     return 0;
     71 }
     72 
     73 
     74 int
     75 sal_strncmp(const char *s1, const char *s2, size_t length)
     76 {
     77     int i = 0;
     78 
     79     while (i < length && *s1 && (*s1 == *s2))
     80     {
     81         s1++;
     82         s2++;
     83         i++;
     84     }
     85     if ((i == length) || (*s1 == *s2))
     86     {
     87         return 0;
     88     }
     89     else if (*s1 < *s2)
     90     {
     91         return -1;
     92     }
     93     else
     94     {
     95         return 1;
     96     }
     97 }
     98 
     99 void *
    100 sal_memcpy(void *dst_void, const void *src_void, size_t len)
    101 {
    102     unsigned char *dst = dst_void;
    103     const unsigned char *src = src_void;
    104 
    105     while (len--) {
    106 	*dst++ = *src++;
    107     }
    108 
    109     return dst_void;
    110 }
    111 
    112 void *
    113 sal_memset(void *dst_void, int val, size_t len)
    114 {
    115     unsigned char *dst = dst_void;
    116 
    117     while (len--) {
    118 	*dst++ = (unsigned char) val;
    119     }
    120 
    121     return dst_void;
    122 }
    123 /* } */
    124 #else
    125 /* { */
    126 #if defined(memcpy)
    127 /* { */
    128 void *sal_memcpy_wrapper(void *dst, const void *src, size_t len)
    129 {
    130 	    return memcpy(dst, src, len);
    131 }
    132 /* } */
    133 #endif
    134 /* } */
    135 #endif /* !RTOS_STRINGS */
    136 /*
    137  * See header of prototype in libc.h
    138  */
    139 int
    140 sal_strnlen(const char *s, size_t max_len)
    141 {
    142     size_t ii = 0;
    143 
    144     while (ii < max_len && s[ii]) {
    145         ii++;
    146     }
    147 
    148     return ii;
    149 }
    150 
    151 /*
    152  * See header of prototype in libc.h
    153  */
    154 char *
    155 sal_strncpy_s(char *dst, const char *src, size_t length)
    156 {
    157     char *ret;
    158     ret = sal_strncpy(dst,src,length);
    159     /*
    160      * Unlike strncpy(), the destination here is ended with NULL regardless
    161      * of the comntents of the source.
    162      */
    163     dst[length - 1] = 0;
    164 
    165     return (ret);
    166 }
    167 
    168 int 
    169 sal_memcmp(const void *m1_void, const void *m2_void, size_t len)
    170 {
    171     const unsigned char *m1 = m1_void, *m2 = m2_void;
    172 
    173     while (len-- != 0) {
    174 	if (*m1 < *m2) {
    175 	    return -1;
    176 	} else if (*m1 > *m2) {
    177 	    return 1;
    178 	}
    179 	m1++;
    180 	m2++;
    181     } 
    182 
    183     return 0;
    184 }
    185 
    186 char *
    187 sal_strdup(const char *s)
    188 {
    189     int len = sal_strlen(s);
    190     char *rc = sal_alloc(len + 1, "sal_strdup");
    191     if (rc != NULL) {
    192         /* coverity[secure_coding] */
    193 	sal_strcpy(rc, s);
    194     }
    195     return rc;
    196 }
    197 
    198 /*
    199  * Duplicate a portion of a string given the number of characters in len.
    200  */
    201 char *
    202 sal_strndup(const char *src, size_t len)
    203 {
    204   register size_t n   = strlen(src);
    205   register char  *dst = NULL;
    206 
    207   if (len < n) n = len;
    208 
    209   dst = sal_alloc(n + 1, "sal_strndup");
    210 
    211   if (dst) {
    212     sal_memcpy(dst, src, n);
    213     dst[n] = '\0';
    214   }
    215   return dst;
    216 }
    217 
    218 char *
    219 sal_strtok_r(char *s1, const char *delim, char **s2)
    220 {
    221     char *ret_str;
    222     char *p;
    223     int len = 0;
    224 
    225     if (s1 == NULL) {
    226         s1 = *s2;
    227         if (s1 == NULL) {
    228             return NULL;
    229         }
    230     }
    231 
    232     p = s1;
    233     /* skip initial delimiters */
    234     while ((*p) && (sal_strchr(delim, *p++) != NULL)) {
    235        len++;    
    236     } 
    237 
    238     s1 += len;
    239 
    240     if (*s1 == '\0') {
    241         return NULL;
    242     }
    243 
    244     ret_str = s1;
    245 
    246     while (*s1) {
    247        if (sal_strchr(delim, *s1) != NULL) {
    248            break;
    249        }
    250        s1++;
    251     }
    252 
    253     if (*s1) {
    254         *s1++ = '\0';
    255     }
    256 
    257     if (s2 != NULL) {
    258         *s2 = s1;
    259     }
    260 
    261     return ret_str;
    262 }
    263 
    264 /*
    265  * sal_ctoi
    266  *
    267  *   Converts a C-style constant to integer.
    268  *   Also supports '0b' prefix for binary.
    269  */
    270 
    271 int 
    272 sal_ctoi(const char *s, char **end)
    273 {
    274     unsigned int	n, neg;
    275     int	base = 10;
    276 
    277     if (s == 0) {
    278 	if (end != 0) {
    279 	    end = 0;
    280 	}
    281 	return 0;
    282     }
    283 
    284     s += (neg = (*s == '-'));
    285 
    286     if (*s == '0') {
    287 	s++;
    288 	if (*s == 'x' || *s == 'X') {
    289 	    base = 16;
    290 	    s++;
    291 	} else if (*s == 'b' || *s == 'B') {
    292 	    base = 2;
    293 	    s++;
    294 	} else {
    295 	    base = 8;
    296 	}
    297     }
    298 
    299     for (n = 0; ((*s >= 'a' && *s < 'a' + base - 10) ||
    300 		 (*s >= 'A' && *s < 'A' + base - 10) ||
    301 		 (*s >= '0' && *s <= '9')); s++) {
    302 	n = n * base + ((*s <= '9' ? *s : *s + 9) & 15);
    303     }
    304 
    305     if (end != 0) {
    306 	*end = (char *) s;
    307     }
    308 
    309     return (int) (neg ? -n : n);
    310 }
    311 
    312 /*
    313  * Curt's Printf
    314  *
    315  * Reasonably complete subset of ANSI-style printf routines.
    316  * Needs only sal_strlen and stdarg.
    317  * Behavior was regressed against Solaris printf(3s) routines (below).
    318  *
    319  * Supported format controls:
    320  *
    321  *	%%	percent sign
    322  *	%c	character
    323  *	%d	integer
    324  *	%hd	short integer
    325  *	%ld	long integer
    326  *	%u	unsigned integer
    327  *	%o	unsigned octal integer
    328  *	%x	unsigned hexadecimal integer (lowercase)
    329  *	%X	unsigned hexadecimal integer (uppercase)
    330  *	%s	string
    331  *	%p	pointer
    332  *	%n	store number of characters output so far
    333  *	%f	float
    334  *	%lf	double		(if COMPILER_HAS_DOUBLE is defined)
    335  *
    336  * Flag modifiers supported:
    337  *	Field width, argument field width (*), left justify (-),
    338  *	zero-fill (0), alternate form (#), always include sign (+),
    339  *	space before positive numbers (space).
    340  *
    341  * Not supported: long long
    342  *
    343  * Functions implemented:
    344  *
    345  * int sal_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap);
    346  * int sal_vsprintf(char *buf, const char *fmt, va_list ap);
    347  * int sal_snprintf(char *buf, size_t bufsize, const char *fmt, ...);
    348  * int sal_sprintf(char *buf, const char *fmt, ...);
    349  */
    350 
    351 void
    352 sal_ltoa(char *buf,             /* Large enough result buffer   */
    353      unsigned long num,         /* Number to convert            */
    354      int base,                  /* Conversion base (2 to 16)    */
    355      int caps,                  /* Capitalize letter digits     */
    356      int prec)                  /* Precision (minimum digits)   */
    357 {
    358     char        tmp[68], *s, *digits;
    359 
    360     digits = (caps ? "0123456789ABCDEF" : "0123456789abcdef");
    361 
    362     s = &tmp[sizeof (tmp) - 1];
    363 
    364     for (*s = 0; num || s == &tmp[sizeof (tmp) - 1]; num /= base, prec--)
    365         *--s = digits[num % base];
    366 
    367     while (prec-- > 0)
    368         *--s = '0';
    369     /* coverity[secure_coding] */
    370     sal_strcpy(buf, s);
    371 }
    372 
    373 void
    374 sal_itoa(char *buf,             /* Large enough result buffer   */
    375      uint32 num,                /* Number to convert            */
    376      int base,                  /* Conversion base (2 to 16)    */
    377      int caps,                  /* Capitalize letter digits     */
    378      int prec)                  /* Precision (minimum digits)   */
    379 {
    380     sal_ltoa(buf, num, base, caps, prec);
    381 }
    382 
    383 #ifdef COMPILER_HAS_DOUBLE
    384 
    385 void
    386 sal_ftoa(char *buf, double f, int decimals)
    387 {
    388     int			exp = 0;
    389     unsigned int	int_part;
    390     double		round;
    391     int			i;
    392 
    393     if (f < 0.0) {
    394 	*buf++ = '-';
    395 	f = -f;
    396     }
    397 
    398     for (round = 0.5, i = 0; i < decimals; i++)
    399 	round /= 10.0;
    400 
    401     f += round;
    402 
    403     if (f >= 4294967296.0)
    404 	while (f >= 10.0) {
    405 	    f /= 10.0;
    406 	    exp++;
    407 	}
    408 
    409     int_part = (unsigned int) f;
    410     f -= int_part;
    411 
    412     sal_itoa(buf, int_part, 10, 0, 0);
    413     while (*buf)
    414 	buf++;
    415 
    416     *buf++ = '.';
    417 
    418     for (i = 0; i < decimals; i++) {
    419 	f *= 10.0;
    420 	int_part = (unsigned int) f;
    421 	f -= int_part;
    422 	*buf++ = '0' + int_part;
    423     }
    424 
    425     if (exp) {
    426 	*buf++ = 'e';
    427 	sal_itoa(buf, exp, 10, 0, 0);
    428     } else
    429 	*buf = 0;
    430 }
    431 
    432 #endif /* COMPILER_HAS_DOUBLE */
    433 
    434 #define X_STORE(c) { 	\
    435         if (PTR_TO_INT(bp) < PTR_TO_INT(be))	\
    436             *bp = (c); 	                        \
    437         bp++; 		                        \
    438 }
    439 
    440 #define X_INF		0x7ffffff0
    441 
    442 int sal_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap)
    443 {
    444     char		c, *bp, *be;
    445     char                *p_null = NULL;
    446     char		*b_inf = p_null - 1;
    447 
    448     bp = buf;
    449     be = (bufsize == X_INF) ? b_inf : &buf[bufsize - 1];
    450 
    451     while ((c = *fmt++) != 0) {
    452 	int 		width = 0, ljust = 0, plus = 0, space = 0;
    453 	int		altform = 0, prec = 0, half = 0, base = 0;
    454 	int		tlong = 0, fillz = 0, plen, pad;
    455 	long		num = 0;
    456 	char		tmp[36], *p = tmp;
    457 #ifdef COMPILER_HAS_DOUBLE
    458     int prec_given = 0;
    459 #endif
    460 
    461 	if (c != '%') {
    462 	    X_STORE(c);
    463 	    continue;
    464 	}
    465 
    466 	for (c = *fmt++; ; c = *fmt++)
    467 	    switch (c) {
    468 	    case 'h': half = 1;	 	break;
    469 	    case 'l': tlong = 1; 	break;
    470 	    case '-': ljust = 1; 	break;
    471 	    case '+': plus = 1; 	break;
    472 	    case ' ': space = 1; 	break;
    473 	    case '0': fillz = 1; 	break;
    474 	    case '#': altform = 1; 	break;
    475 	    case '*': width = -1;	break;	/* Mark as need-to-fetch */
    476 	    case '.':
    477 		if ((c = *fmt++) == '*')
    478 		    prec = -1;			/* Mark as need-to-fetch */
    479 		else {
    480 		    for (prec = 0; c >= '0' && c <= '9'; c = *fmt++)
    481 			prec = prec * 10 + (c - '0');
    482 		    fmt--;
    483 		}
    484 #ifdef COMPILER_HAS_DOUBLE
    485 		prec_given = 1;
    486 #endif
    487 		break;
    488 	    default:
    489 		if (c >= '1' && c <= '9') {
    490 		    for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
    491 			width = width * 10 + (c - '0');
    492 		    fmt--;
    493 		} else
    494 		    goto break_for;
    495 		break;
    496 	    }
    497     break_for:
    498 
    499 	if (width == -1)
    500 	    width = va_arg(ap,int);
    501 	if (prec == -1)
    502 	    prec = va_arg(ap,int);
    503 
    504 	if (c == 0)
    505 	    break;
    506 
    507 	switch (c) {
    508 	case 'd':
    509 	case 'i':
    510 	    num = tlong ? va_arg(ap, long) : va_arg(ap, int);
    511 	    if (half)
    512 		num = (int) (short) num;
    513             else if (!tlong)
    514                 num = (int) num;
    515 	    /* For zero-fill, the sign must be to the left of the zeroes */
    516 	    if (fillz && (num < 0 || plus || space)) {
    517 		X_STORE(num < 0 ? '-' : space ? ' ' : '+');
    518 		if (width > 0)
    519 		    width--;
    520 		if (num < 0)
    521 		    num = -num;
    522 	    }
    523 	    if (! fillz) {
    524 		if (num < 0) {
    525 		    *p++ = '-';
    526 		    num = -num;
    527 		} else if (plus)
    528 		    *p++ = '+';
    529 		else if (space)
    530 		    *p++ = ' ';
    531 	    }
    532 	    base = 10;
    533 	    break;
    534 	case 'u':
    535 	    num = tlong ? va_arg(ap, long) : va_arg(ap, int);
    536 	    if (half)
    537 		num = (int) (unsigned short) num;
    538             else if (!tlong)
    539                 num = (long) (unsigned int) num;
    540 	    base = 10;
    541 	    break;
    542 	case 'p':
    543             *p++ = '0';
    544             *p++ = 'x';
    545             tlong = 1;
    546             altform = 0;
    547 	    /* Fall through */
    548 	case 'x':
    549 	case 'X':
    550 	    num = tlong ? va_arg(ap, long) : va_arg(ap, int);
    551 	    if (half)
    552 		num = (int) (unsigned short) num;
    553             else if (!tlong)
    554                 num = (long) (unsigned int) num;
    555 	    if (altform) {
    556 		prec += 2;
    557 		*p++ = '0';
    558 		*p++ = c;
    559 	    }
    560 	    base = 16;
    561 	    break;
    562 	case 'o':
    563 	case 'O':
    564 	    num = tlong ? va_arg(ap, long) : va_arg(ap, int);
    565 	    if (half)
    566 		num = (int) (unsigned short) num;
    567             else if (!tlong)
    568                 num = (long) (unsigned int) num;
    569 	    if (altform) {
    570 		prec++;
    571 		*p++ = '0';
    572 	    }
    573 	    base = 8;
    574 	    break;
    575 #ifdef COMPILER_HAS_DOUBLE
    576 	case 'f':
    577 	    {
    578 		double		f;
    579 
    580 		f = va_arg(ap, double);
    581 		if (! prec_given)
    582 		    prec = 6;
    583 		sal_ftoa(p, f, prec);
    584 		fillz = 0;
    585 		p = tmp;
    586 		prec = X_INF;
    587 	    }
    588 	    break;
    589 #endif /* COMPILER_HAS_DOUBLE */
    590 	case 's':
    591 	    p = va_arg(ap,char *);
    592 	    if (prec == 0)
    593 		prec = X_INF;
    594 	    break;
    595 	case 'c':
    596 	    p[0] = va_arg(ap,int);
    597 	    p[1] = 0;
    598 	    prec = 1;
    599 	    break;
    600 	case 'n':
    601 	    *va_arg(ap,int *) = bp - buf;
    602 	    p[0] = 0;
    603 	    break;
    604 	case '%':
    605 	    p[0] = '%';
    606 	    p[1] = 0;
    607 	    prec = 1;
    608 	    break;
    609 	default:
    610 	    X_STORE(c);
    611 	    continue;
    612 	}
    613 
    614 	if (base != 0) {
    615 	    sal_ltoa(p, num, base, (c == 'X'), prec);
    616 	    if (prec)
    617 		fillz = 0;
    618 	    p = tmp;
    619 	    prec = X_INF;
    620 	}
    621 
    622 	if ((plen = sal_strlen(p)) > prec)
    623 	    plen = prec;
    624 
    625 	if (width < plen)
    626 	    width = plen;
    627 
    628 	pad = width - plen;
    629 
    630 	while (! ljust && pad-- > 0)
    631 	    X_STORE(fillz ? '0' : ' ');
    632 	for (; plen-- > 0 && width-- > 0; p++)
    633 	    X_STORE(*p);
    634 	while (pad-- > 0)
    635 	    X_STORE(' ');
    636     }
    637 
    638     if ((be == b_inf) || (bp < be))
    639 	*bp = 0;
    640     else
    641     /*    coverity[var_deref_op : FALSE]    */
    642 	*be = 0;
    643 
    644     return (bp - buf);
    645 }
    646 
    647 int sal_vsprintf(char *buf, const char *fmt, va_list ap)
    648 {
    649     return sal_vsnprintf(buf, (size_t) X_INF, fmt, ap);
    650 }
    651 
    652 int sal_snprintf(char *buf, size_t bufsize, const char *fmt, ...)
    653 {
    654     va_list		ap;
    655     int			r;
    656 
    657     va_start(ap,fmt);
    658     r = sal_vsnprintf(buf, bufsize, fmt, ap);
    659     va_end(ap);
    660 
    661     return r;
    662 }
    663 
    664 int sal_sprintf(char *buf, const char *fmt, ...)
    665 {
    666     va_list		ap;
    667     int			r;
    668 
    669     va_start(ap,fmt);
    670     r = sal_vsnprintf(buf, (size_t) X_INF, fmt, ap);
    671     va_end(ap);
    672 
    673     return r;
    674 }
    675 
    676 void sal_free_safe(void* ptr)
    677 {
    678     if(ptr) {
    679         sal_free(ptr); 
    680     }   
    681 }
    682 uint32 sal_ceil_func(uint32 numerators , uint32 denominator)
    683 {
    684     uint32  result;
    685     if (denominator == 0) {
    686         return 0xFFFFFFFF;
    687     }
    688     result = numerators / denominator;
    689     if (numerators % denominator != 0) {
    690         result++;
    691     }
    692     return result;
    693 }
    694 uint32 sal_floor_func(uint32 numerators , uint32 denominator)
    695 {
    696     uint32  result;
    697     if (denominator == 0) {
    698         return 0xFFFFFFFF;
    699     }
    700     result = numerators / denominator;
    701     return result;
    702 }
    703       
    704 
    705 static unsigned long next = 1;
    706 
    707 int sal_rand(void) {
    708     next = next * 1103515245 + 12345;
    709 
    710     /* SAL_RAND_MAX assumed to be 32767 */
    711     return ((unsigned)(next / 65536) % (SAL_RAND_MAX + 1));
    712 }
    713 
    714 void sal_srand(unsigned seed) {
    715     next = seed;
    716 }