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 }