|  | // Basic string routines.  Not hardware optimized, but not shabby. | 
|  |  | 
|  | #ifdef __SHARC__ | 
|  | #pragma nosharc | 
|  | #endif | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <ros/memlayout.h> | 
|  | #include <assert.h> | 
|  |  | 
|  | int | 
|  | strlen(const char *s) | 
|  | { | 
|  | int n; | 
|  |  | 
|  | for (n = 0; *s != '\0'; s++) | 
|  | n++; | 
|  | return n; | 
|  | } | 
|  |  | 
|  | int | 
|  | strnlen(const char *s, size_t size) | 
|  | { | 
|  | int n; | 
|  |  | 
|  | for (n = 0; size > 0 && *s != '\0'; s++, size--) | 
|  | n++; | 
|  | return n; | 
|  | } | 
|  |  | 
|  | /* zra: These aren't being used, and they are dangerous, so I'm rm'ing them | 
|  | char * | 
|  | strcpy(char *dst, const char *src) | 
|  | { | 
|  | char *ret; | 
|  |  | 
|  | ret = dst; | 
|  | while ((*dst++ = *src++) != '\0') | 
|  | ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | char * | 
|  | strcat(char *dst, const char *src) | 
|  | { | 
|  | strcpy(dst+strlen(dst),src); | 
|  | return dst; | 
|  | } | 
|  | */ | 
|  |  | 
|  | char * | 
|  | strncpy(char *dst, const char *src, size_t size) { | 
|  | size_t i; | 
|  | char *ret; | 
|  |  | 
|  | ret = dst; | 
|  | for (i = 0; i < size; i++) { | 
|  | // TODO: ivy bitches about this | 
|  | *dst++ = *src; | 
|  | // If strlen(src) < size, null-pad 'dst' out to 'size' chars | 
|  | if (*src != '\0') | 
|  | src++; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | size_t | 
|  | strlcpy(char *dst, const char *src, size_t size) | 
|  | { | 
|  | char *dst_in; | 
|  |  | 
|  | dst_in = dst; | 
|  | if (size > 0) { | 
|  | while (--size > 0 && *src != '\0') | 
|  | *dst++ = *src++; | 
|  | *dst = '\0'; | 
|  | } | 
|  | return dst - dst_in; | 
|  | } | 
|  |  | 
|  | int | 
|  | strcmp(const char *p, const char *q) | 
|  | { | 
|  | while (*p && *p == *q) | 
|  | p++, q++; | 
|  | return (int) ((unsigned char) *p - (unsigned char) *q); | 
|  | } | 
|  |  | 
|  | int | 
|  | strncmp(const char *p, const char *q, size_t n) | 
|  | { | 
|  | while (n > 0 && *p && *p == *q) | 
|  | n--, p++, q++; | 
|  | if (n == 0) | 
|  | return 0; | 
|  | else | 
|  | return (int) ((unsigned char) *p - (unsigned char) *q); | 
|  | } | 
|  |  | 
|  | // Return a pointer to the first occurrence of 'c' in 's', | 
|  | // or a null pointer if the string has no 'c'. | 
|  | char * | 
|  | strchr(const char *s, char c) | 
|  | { | 
|  | for (; *s; s++) | 
|  | if (*s == c) | 
|  | return (char *) s; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // Return a pointer to the last occurrence of 'c' in 's', | 
|  | // or a null pointer if the string has no 'c'. | 
|  | char * | 
|  | strrchr(const char *s, char c) | 
|  | { | 
|  | char *lastc = NULL; | 
|  | for (; *s; s++) | 
|  | if (*s == c){ | 
|  | lastc = (char*)s; | 
|  | } | 
|  | return lastc; | 
|  | } | 
|  |  | 
|  | void * | 
|  | memchr(void* mem, int chr, int len) | 
|  | { | 
|  | char* s = (char*)mem; | 
|  | for(int i = 0; i < len; i++) | 
|  | if(s[i] == (char)chr) | 
|  | return s+i; | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | // Return a pointer to the first occurrence of 'c' in 's', | 
|  | // or a pointer to the string-ending null character if the string has no 'c'. | 
|  | char * | 
|  | strfind(const char *s, char c) | 
|  | { | 
|  | for (; *s; s++) | 
|  | if (*s == c) | 
|  | break; | 
|  | return (char *) s; | 
|  | } | 
|  |  | 
|  | // memset aligned words. | 
|  | static inline void * | 
|  | memsetw(long* _v, long c, size_t n) | 
|  | { | 
|  | long *start, *end, *v; | 
|  |  | 
|  | start = _v; | 
|  | end = _v + n/sizeof(long); | 
|  | v = _v; | 
|  | c = c & 0xff; | 
|  | c = c | c<<8; | 
|  | c = c | c<<16; | 
|  | #if NUM_ADDR_BITS == 64 | 
|  | c = c | c<<32; | 
|  | #elif NUM_ADDR_BITS != 32 | 
|  | # error | 
|  | #endif | 
|  |  | 
|  | while(v < end - (8-1)) | 
|  | { | 
|  | v[3] = v[2] = v[1] = v[0] = c; | 
|  | v += 4; | 
|  | v[3] = v[2] = v[1] = v[0] = c; | 
|  | v += 4; | 
|  | } | 
|  |  | 
|  | while(v < end) | 
|  | *v++ = c; | 
|  |  | 
|  | return start; | 
|  | } | 
|  |  | 
|  | // copy aligned words. | 
|  | // unroll 9 ways to get multiple misses in flight | 
|  | #define memcpyw(type, _dst, _src, n) \ | 
|  | do { \ | 
|  | type* restrict src = (type*)(_src); \ | 
|  | type* restrict dst = (type*)(_dst); \ | 
|  | type* srcend = src + (n)/sizeof(type); \ | 
|  | type* dstend = dst + (n)/sizeof(type); \ | 
|  | while (dst < dstend - (9-1)) { \ | 
|  | dst[0] = src[0]; \ | 
|  | dst[1] = src[1]; \ | 
|  | dst[2] = src[2]; \ | 
|  | dst[3] = src[3]; \ | 
|  | dst[4] = src[4]; \ | 
|  | dst[5] = src[5]; \ | 
|  | dst[6] = src[6]; \ | 
|  | dst[7] = src[7]; \ | 
|  | dst[8] = src[8]; \ | 
|  | src += 9; \ | 
|  | dst += 9; \ | 
|  | } \ | 
|  | while(dst < dstend) \ | 
|  | *dst++ = *src++; \ | 
|  | } while(0) | 
|  |  | 
|  | void * | 
|  | memset(void *COUNT(_n) v, int c, size_t _n) | 
|  | { | 
|  | char *BND(v,v+_n) p; | 
|  | size_t n0; | 
|  | size_t n = _n; | 
|  |  | 
|  | if (n == 0) return NULL; // zra: complain here? | 
|  |  | 
|  | p = v; | 
|  |  | 
|  | while (n > 0 && ((uintptr_t)p & (sizeof(long)-1))) | 
|  | { | 
|  | *p++ = c; | 
|  | n--; | 
|  | } | 
|  |  | 
|  | if (n >= sizeof(long)) | 
|  | { | 
|  | n0 = n / sizeof(long) * sizeof(long); | 
|  | memsetw((long*)p, c, n0); | 
|  | n -= n0; | 
|  | p += n0; | 
|  | } | 
|  |  | 
|  | while (n > 0) | 
|  | { | 
|  | *p++ = c; | 
|  | n--; | 
|  | } | 
|  |  | 
|  | return v; | 
|  | } | 
|  |  | 
|  | void * | 
|  | memcpy(void* dst, const void* src, size_t _n) | 
|  | { | 
|  | const char* s; | 
|  | char* d; | 
|  | size_t n0 = 0; | 
|  | size_t n = _n; | 
|  | int align = sizeof(long)-1; | 
|  |  | 
|  | s = src; | 
|  | d = dst; | 
|  |  | 
|  | if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(long)-1)) == 0) | 
|  | { | 
|  | n0 = n / sizeof(long) * sizeof(long); | 
|  | memcpyw(long, d, s, n0); | 
|  | } | 
|  | else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(int)-1)) == 0) | 
|  | { | 
|  | n0 = n / sizeof(int) * sizeof(int); | 
|  | memcpyw(int, d, s, n0); | 
|  | } | 
|  | else if ((((uintptr_t)s | (uintptr_t)d) & (sizeof(short)-1)) == 0) | 
|  | { | 
|  | n0 = n / sizeof(short) * sizeof(short); | 
|  | memcpyw(short, d, s, n0); | 
|  | } | 
|  |  | 
|  | n -= n0; | 
|  | s += n0; | 
|  | d += n0; | 
|  |  | 
|  | while (n-- > 0) | 
|  | *d++ = *s++; | 
|  |  | 
|  | return dst; | 
|  | } | 
|  |  | 
|  | void * | 
|  | memmove(void *COUNT(_n) dst, const void *COUNT(_n) src, size_t _n) | 
|  | { | 
|  | #ifdef CONFIG_X86 | 
|  | bcopy(src, dst, _n); | 
|  | return dst; | 
|  | #else | 
|  | const char *BND(src,src+_n) s; | 
|  | char *BND(dst,dst+_n) d; | 
|  | size_t n = _n; | 
|  |  | 
|  | s = src; | 
|  | d = dst; | 
|  | if (s < d && s + n > d) { | 
|  | s += n; | 
|  | d += n; | 
|  | while (n-- > 0) | 
|  | *--d = *--s; | 
|  | } else | 
|  | while (n-- > 0) | 
|  | *d++ = *s++; | 
|  |  | 
|  | return dst; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | int | 
|  | memcmp(const void *COUNT(n) v1, const void *COUNT(n) v2, size_t n) | 
|  | { | 
|  | const uint8_t *BND(v1,v1+n) s1 = (const uint8_t *) v1; | 
|  | const uint8_t *BND(v2,v2+n) s2 = (const uint8_t *) v2; | 
|  |  | 
|  | while (n-- > 0) { | 
|  | if (*s1 != *s2) | 
|  | return (int) *s1 - (int) *s2; | 
|  | s1++, s2++; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void * | 
|  | memfind(const void *COUNT(n) _s, int c, size_t n) | 
|  | { | 
|  | const void *SNT ends = (const char *) _s + n; | 
|  | const void *BND(_s,_s + n) s = _s; | 
|  | for (; s < ends; s++) | 
|  | if (*(const unsigned char *) s == (unsigned char) c) | 
|  | break; | 
|  | return (void *BND(_s,_s+n)) s; | 
|  | } | 
|  |  | 
|  | long | 
|  | strtol(const char *s, char **endptr, int base) | 
|  | { | 
|  | int neg = 0; | 
|  | long val = 0; | 
|  |  | 
|  | // gobble initial whitespace | 
|  | while (*s == ' ' || *s == '\t') | 
|  | s++; | 
|  |  | 
|  | // plus/minus sign | 
|  | if (*s == '+') | 
|  | s++; | 
|  | else if (*s == '-') | 
|  | s++, neg = 1; | 
|  |  | 
|  | // hex or octal base prefix | 
|  | if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) | 
|  | s += 2, base = 16; | 
|  | else if (base == 0 && s[0] == '0') | 
|  | s++, base = 8; | 
|  | else if (base == 0) | 
|  | base = 10; | 
|  |  | 
|  | // digits | 
|  | while (1) { | 
|  | int dig; | 
|  |  | 
|  | if (*s >= '0' && *s <= '9') | 
|  | dig = *s - '0'; | 
|  | else if (*s >= 'a' && *s <= 'z') | 
|  | dig = *s - 'a' + 10; | 
|  | else if (*s >= 'A' && *s <= 'Z') | 
|  | dig = *s - 'A' + 10; | 
|  | else | 
|  | break; | 
|  | if (dig >= base) | 
|  | break; | 
|  | s++, val = (val * base) + dig; | 
|  | // we don't properly detect overflow! | 
|  | } | 
|  |  | 
|  | if (endptr) | 
|  | *endptr = (char *) s; | 
|  | return (neg ? -val : val); | 
|  | } | 
|  |  | 
|  | unsigned long | 
|  | strtoul(const char *s, char **endptr, int base) | 
|  | { | 
|  | int neg = 0; | 
|  | unsigned long val = 0; | 
|  |  | 
|  | // gobble initial whitespace | 
|  | while (*s == ' ' || *s == '\t') | 
|  | s++; | 
|  |  | 
|  | // plus/minus sign | 
|  | if (*s == '+') | 
|  | s++; | 
|  | else if (*s == '-') | 
|  | s++, neg = 1; | 
|  |  | 
|  | // hex or octal base prefix | 
|  | if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) | 
|  | s += 2, base = 16; | 
|  | else if (base == 0 && s[0] == '0') | 
|  | s++, base = 8; | 
|  | else if (base == 0) | 
|  | base = 10; | 
|  |  | 
|  | // digits | 
|  | while (1) { | 
|  | int dig; | 
|  |  | 
|  | if (*s >= '0' && *s <= '9') | 
|  | dig = *s - '0'; | 
|  | else if (*s >= 'a' && *s <= 'z') | 
|  | dig = *s - 'a' + 10; | 
|  | else if (*s >= 'A' && *s <= 'Z') | 
|  | dig = *s - 'A' + 10; | 
|  | else | 
|  | break; | 
|  | if (dig >= base) | 
|  | break; | 
|  | s++, val = (val * base) + dig; | 
|  | // we don't properly detect overflow! | 
|  | } | 
|  |  | 
|  | if (endptr) | 
|  | *endptr = (char *) s; | 
|  | return (neg ? -val : val); | 
|  | } | 
|  |  | 
|  | int atoi(const char *s) | 
|  | { | 
|  | if (!s) | 
|  | return 0; | 
|  | if (s[0] == '0' && s[1] == 'x') | 
|  | warn("atoi() used on a hex string!"); | 
|  | // no overflow detection | 
|  | return (int)strtol(s,NULL,10); | 
|  | } | 
|  |  | 
|  | int sigchecksum(void *address, int length) | 
|  | { | 
|  | uint8_t *p, sum; | 
|  |  | 
|  | sum = 0; | 
|  | for (p = address; length-- > 0; p++) | 
|  | sum += *p; | 
|  |  | 
|  | return sum; | 
|  | } | 
|  |  | 
|  | void *sigscan(uint8_t *address, int length, char *signature) | 
|  | { | 
|  | uint8_t *e, *p; | 
|  | int siglength; | 
|  |  | 
|  | e = address + length; | 
|  | siglength = strlen(signature); | 
|  | for (p = address; p + siglength < e; p += 16) { | 
|  | if (memcmp(p, signature, siglength)) | 
|  | continue; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | return NULL; | 
|  | } |