14b6da826SThomas Huth /* 24b6da826SThomas Huth * libc string functions 34b6da826SThomas Huth * 44b6da826SThomas Huth * This code is free software; you can redistribute it and/or modify it 54b6da826SThomas Huth * under the terms of the GNU Library General Public License version 2. 64b6da826SThomas Huth */ 74b6da826SThomas Huth 87d36db35SAvi Kivity #include "libcflat.h" 9*5927d1c2SAndrew Jones #include "ctype.h" 10b5501ed0SNikos Nikoleris #include "stdlib.h" 11b5501ed0SNikos Nikoleris #include "linux/compiler.h" 127d36db35SAvi Kivity 13b5501ed0SNikos Nikoleris size_t strlen(const char *buf) 147d36db35SAvi Kivity { 15b5501ed0SNikos Nikoleris size_t len = 0; 167d36db35SAvi Kivity 177d36db35SAvi Kivity while (*buf++) 187d36db35SAvi Kivity ++len; 197d36db35SAvi Kivity return len; 207d36db35SAvi Kivity } 217d36db35SAvi Kivity 22b5501ed0SNikos Nikoleris size_t strnlen(const char *buf, size_t maxlen) 23b5501ed0SNikos Nikoleris { 24b5501ed0SNikos Nikoleris const char *sc; 25b5501ed0SNikos Nikoleris 26b5501ed0SNikos Nikoleris for (sc = buf; maxlen-- && *sc != '\0'; ++sc) 27b5501ed0SNikos Nikoleris /* nothing */ ; 28b5501ed0SNikos Nikoleris return sc - buf; 29b5501ed0SNikos Nikoleris } 30b5501ed0SNikos Nikoleris 317d36db35SAvi Kivity char *strcat(char *dest, const char *src) 327d36db35SAvi Kivity { 337d36db35SAvi Kivity char *p = dest; 347d36db35SAvi Kivity 357d36db35SAvi Kivity while (*p) 367d36db35SAvi Kivity ++p; 377d36db35SAvi Kivity while ((*p++ = *src++) != 0) 387d36db35SAvi Kivity ; 397d36db35SAvi Kivity return dest; 407d36db35SAvi Kivity } 417d36db35SAvi Kivity 42782ebe33SAndrew Jones char *strcpy(char *dest, const char *src) 43782ebe33SAndrew Jones { 44782ebe33SAndrew Jones *dest = 0; 45782ebe33SAndrew Jones return strcat(dest, src); 46782ebe33SAndrew Jones } 47782ebe33SAndrew Jones 484fd53297SRadim Krčmář int strncmp(const char *a, const char *b, size_t n) 494fd53297SRadim Krčmář { 504fd53297SRadim Krčmář for (; n--; ++a, ++b) 514fd53297SRadim Krčmář if (*a != *b || *a == '\0') 524fd53297SRadim Krčmář return *a - *b; 534fd53297SRadim Krčmář 544fd53297SRadim Krčmář return 0; 554fd53297SRadim Krčmář } 564fd53297SRadim Krčmář 5769da6c87SAvi Kivity int strcmp(const char *a, const char *b) 5869da6c87SAvi Kivity { 594fd53297SRadim Krčmář return strncmp(a, b, SIZE_MAX); 6069da6c87SAvi Kivity } 6169da6c87SAvi Kivity 62782ebe33SAndrew Jones char *strchr(const char *s, int c) 63782ebe33SAndrew Jones { 64782ebe33SAndrew Jones while (*s != (char)c) 65782ebe33SAndrew Jones if (*s++ == '\0') 66782ebe33SAndrew Jones return NULL; 67782ebe33SAndrew Jones return (char *)s; 68782ebe33SAndrew Jones } 69782ebe33SAndrew Jones 70b5501ed0SNikos Nikoleris char *strrchr(const char *s, int c) 71b5501ed0SNikos Nikoleris { 72b5501ed0SNikos Nikoleris const char *last = NULL; 73b5501ed0SNikos Nikoleris do { 74b5501ed0SNikos Nikoleris if (*s == (char)c) 75b5501ed0SNikos Nikoleris last = s; 76b5501ed0SNikos Nikoleris } while (*s++); 77b5501ed0SNikos Nikoleris return (char *)last; 78b5501ed0SNikos Nikoleris } 79b5501ed0SNikos Nikoleris 80546914b4SNikos Nikoleris char *strchrnul(const char *s, int c) 81546914b4SNikos Nikoleris { 82546914b4SNikos Nikoleris while (*s && *s != (char)c) 83546914b4SNikos Nikoleris s++; 84546914b4SNikos Nikoleris return (char *)s; 85546914b4SNikos Nikoleris } 86546914b4SNikos Nikoleris 8753da5cc0SAndrew Jones char *strstr(const char *s1, const char *s2) 8853da5cc0SAndrew Jones { 8953da5cc0SAndrew Jones size_t l1, l2; 9053da5cc0SAndrew Jones 9153da5cc0SAndrew Jones l2 = strlen(s2); 9253da5cc0SAndrew Jones if (!l2) 9353da5cc0SAndrew Jones return (char *)s1; 9453da5cc0SAndrew Jones l1 = strlen(s1); 9553da5cc0SAndrew Jones while (l1 >= l2) { 9653da5cc0SAndrew Jones l1--; 9753da5cc0SAndrew Jones if (!memcmp(s1, s2, l2)) 9853da5cc0SAndrew Jones return (char *)s1; 9953da5cc0SAndrew Jones s1++; 10053da5cc0SAndrew Jones } 10153da5cc0SAndrew Jones return NULL; 10253da5cc0SAndrew Jones } 10353da5cc0SAndrew Jones 1047d36db35SAvi Kivity void *memset(void *s, int c, size_t n) 1057d36db35SAvi Kivity { 1067d36db35SAvi Kivity size_t i; 1077d36db35SAvi Kivity char *a = s; 1087d36db35SAvi Kivity 1097d36db35SAvi Kivity for (i = 0; i < n; ++i) 1107d36db35SAvi Kivity a[i] = c; 1117d36db35SAvi Kivity 1127d36db35SAvi Kivity return s; 1137d36db35SAvi Kivity } 1141b708e8cSJason Wang 1158d68030eSArthur Chunqi Li void *memcpy(void *dest, const void *src, size_t n) 1168d68030eSArthur Chunqi Li { 1178d68030eSArthur Chunqi Li size_t i; 1188d68030eSArthur Chunqi Li char *a = dest; 1198d68030eSArthur Chunqi Li const char *b = src; 1208d68030eSArthur Chunqi Li 1218d68030eSArthur Chunqi Li for (i = 0; i < n; ++i) 1228d68030eSArthur Chunqi Li a[i] = b[i]; 1238d68030eSArthur Chunqi Li 1248d68030eSArthur Chunqi Li return dest; 1258d68030eSArthur Chunqi Li } 1268d68030eSArthur Chunqi Li 127782ebe33SAndrew Jones int memcmp(const void *s1, const void *s2, size_t n) 128782ebe33SAndrew Jones { 129782ebe33SAndrew Jones const unsigned char *a = s1, *b = s2; 130782ebe33SAndrew Jones int ret = 0; 131782ebe33SAndrew Jones 132782ebe33SAndrew Jones while (n--) { 133782ebe33SAndrew Jones ret = *a - *b; 134782ebe33SAndrew Jones if (ret) 135782ebe33SAndrew Jones break; 136782ebe33SAndrew Jones ++a, ++b; 137782ebe33SAndrew Jones } 138782ebe33SAndrew Jones return ret; 139782ebe33SAndrew Jones } 140782ebe33SAndrew Jones 141782ebe33SAndrew Jones void *memmove(void *dest, const void *src, size_t n) 142782ebe33SAndrew Jones { 143782ebe33SAndrew Jones const unsigned char *s = src; 144782ebe33SAndrew Jones unsigned char *d = dest; 145782ebe33SAndrew Jones 146782ebe33SAndrew Jones if (d <= s) { 147782ebe33SAndrew Jones while (n--) 148782ebe33SAndrew Jones *d++ = *s++; 149782ebe33SAndrew Jones } else { 150782ebe33SAndrew Jones d += n, s += n; 151782ebe33SAndrew Jones while (n--) 152782ebe33SAndrew Jones *--d = *--s; 153782ebe33SAndrew Jones } 154782ebe33SAndrew Jones return dest; 155782ebe33SAndrew Jones } 156782ebe33SAndrew Jones 157782ebe33SAndrew Jones void *memchr(const void *s, int c, size_t n) 158782ebe33SAndrew Jones { 159782ebe33SAndrew Jones const unsigned char *str = s, chr = (unsigned char)c; 160782ebe33SAndrew Jones 161782ebe33SAndrew Jones while (n--) 162782ebe33SAndrew Jones if (*str++ == chr) 163782ebe33SAndrew Jones return (void *)(str - 1); 164782ebe33SAndrew Jones return NULL; 165782ebe33SAndrew Jones } 166782ebe33SAndrew Jones 1677f1ca26cSAndrew Jones static unsigned long long __strtoll(const char *nptr, char **endptr, 1680e981298SAndrew Jones int base, bool is_signed, bool is_longlong) 1690e981298SAndrew Jones { 1707f1ca26cSAndrew Jones unsigned long long ull = 0; 171b5501ed0SNikos Nikoleris const char *s = nptr; 1721b708e8cSJason Wang int neg, c; 1731b708e8cSJason Wang 174b5501ed0SNikos Nikoleris assert(base == 0 || (base >= 2 && base <= 36)); 175b5501ed0SNikos Nikoleris 176b5501ed0SNikos Nikoleris while (isspace(*s)) 1771b708e8cSJason Wang s++; 178b5501ed0SNikos Nikoleris 1791b708e8cSJason Wang if (*s == '-') { 1801b708e8cSJason Wang neg = 1; 1811b708e8cSJason Wang s++; 1821b708e8cSJason Wang } else { 1831b708e8cSJason Wang neg = 0; 1841b708e8cSJason Wang if (*s == '+') 1851b708e8cSJason Wang s++; 1861b708e8cSJason Wang } 1871b708e8cSJason Wang 188b5501ed0SNikos Nikoleris if (base == 0 || base == 16) { 189b5501ed0SNikos Nikoleris if (*s == '0') { 190b5501ed0SNikos Nikoleris s++; 191b5501ed0SNikos Nikoleris if (*s == 'x' || *s == 'X') { 192b5501ed0SNikos Nikoleris s++; 193b5501ed0SNikos Nikoleris base = 16; 194b5501ed0SNikos Nikoleris } else if (base == 0) 195b5501ed0SNikos Nikoleris base = 8; 196b5501ed0SNikos Nikoleris } else if (base == 0) 197b5501ed0SNikos Nikoleris base = 10; 198b5501ed0SNikos Nikoleris } 199b5501ed0SNikos Nikoleris 2001b708e8cSJason Wang while (*s) { 201b5501ed0SNikos Nikoleris if (*s >= '0' && *s < '0' + base && *s <= '9') 2021b708e8cSJason Wang c = *s - '0'; 203b5501ed0SNikos Nikoleris else if (*s >= 'a' && *s < 'a' + base - 10) 204b5501ed0SNikos Nikoleris c = *s - 'a' + 10; 205b5501ed0SNikos Nikoleris else if (*s >= 'A' && *s < 'A' + base - 10) 206b5501ed0SNikos Nikoleris c = *s - 'A' + 10; 207b5501ed0SNikos Nikoleris else 208b5501ed0SNikos Nikoleris break; 209b5501ed0SNikos Nikoleris 2107f1ca26cSAndrew Jones if (!is_longlong) { 211b5501ed0SNikos Nikoleris if (is_signed) { 2127f1ca26cSAndrew Jones long sl = (long)ull; 2137f1ca26cSAndrew Jones assert(!check_mul_overflow(sl, base)); 2147f1ca26cSAndrew Jones assert(!check_add_overflow(sl * base, c)); 215b5501ed0SNikos Nikoleris } else { 2167f1ca26cSAndrew Jones unsigned long ul = (unsigned long)ull; 2177f1ca26cSAndrew Jones assert(!check_mul_overflow(ul, base)); 2187f1ca26cSAndrew Jones assert(!check_add_overflow(ul * base, c)); 2197f1ca26cSAndrew Jones } 2207f1ca26cSAndrew Jones } else { 2217f1ca26cSAndrew Jones if (is_signed) { 2227f1ca26cSAndrew Jones long long sll = (long long)ull; 2237f1ca26cSAndrew Jones assert(!check_mul_overflow(sll, base)); 2247f1ca26cSAndrew Jones assert(!check_add_overflow(sll * base, c)); 2257f1ca26cSAndrew Jones } else { 2267f1ca26cSAndrew Jones assert(!check_mul_overflow(ull, base)); 2277f1ca26cSAndrew Jones assert(!check_add_overflow(ull * base, c)); 2287f1ca26cSAndrew Jones } 229b5501ed0SNikos Nikoleris } 230b5501ed0SNikos Nikoleris 2317f1ca26cSAndrew Jones ull = ull * base + c; 2321b708e8cSJason Wang s++; 2331b708e8cSJason Wang } 2341b708e8cSJason Wang 2351b708e8cSJason Wang if (neg) 2367f1ca26cSAndrew Jones ull = -ull; 2371b708e8cSJason Wang 238b5501ed0SNikos Nikoleris if (endptr) 239b5501ed0SNikos Nikoleris *endptr = (char *)s; 240b5501ed0SNikos Nikoleris 2417f1ca26cSAndrew Jones return ull; 2421b708e8cSJason Wang } 24369205bf1SAndrew Jones 244b5501ed0SNikos Nikoleris long int strtol(const char *nptr, char **endptr, int base) 245b5501ed0SNikos Nikoleris { 2467f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, true, false); 247b5501ed0SNikos Nikoleris } 248b5501ed0SNikos Nikoleris 249b5501ed0SNikos Nikoleris unsigned long int strtoul(const char *nptr, char **endptr, int base) 250b5501ed0SNikos Nikoleris { 2517f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, false, false); 2527f1ca26cSAndrew Jones } 2537f1ca26cSAndrew Jones 2547f1ca26cSAndrew Jones long long int strtoll(const char *nptr, char **endptr, int base) 2557f1ca26cSAndrew Jones { 2567f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, true, true); 2577f1ca26cSAndrew Jones } 2587f1ca26cSAndrew Jones 2597f1ca26cSAndrew Jones unsigned long long int strtoull(const char *nptr, char **endptr, int base) 2607f1ca26cSAndrew Jones { 2617f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, false, true); 262b5501ed0SNikos Nikoleris } 263b5501ed0SNikos Nikoleris 264b5501ed0SNikos Nikoleris long atol(const char *ptr) 265b5501ed0SNikos Nikoleris { 266b5501ed0SNikos Nikoleris return strtol(ptr, NULL, 10); 267b5501ed0SNikos Nikoleris } 268b5501ed0SNikos Nikoleris 26969205bf1SAndrew Jones extern char **environ; 27069205bf1SAndrew Jones 27169205bf1SAndrew Jones char *getenv(const char *name) 27269205bf1SAndrew Jones { 27369205bf1SAndrew Jones char **envp = environ, *delim; 2744837df6eSAndrew Jones int len; 27569205bf1SAndrew Jones 27669205bf1SAndrew Jones while (*envp) { 27769205bf1SAndrew Jones delim = strchr(*envp, '='); 2784837df6eSAndrew Jones assert(delim); 2794837df6eSAndrew Jones len = delim - *envp; 2804837df6eSAndrew Jones if (memcmp(name, *envp, len) == 0 && !name[len]) 28169205bf1SAndrew Jones return delim + 1; 28269205bf1SAndrew Jones ++envp; 28369205bf1SAndrew Jones } 28469205bf1SAndrew Jones return NULL; 28569205bf1SAndrew Jones } 286875b97b3SPeter Feiner 287875b97b3SPeter Feiner /* Very simple glob matching. Allows '*' at beginning and end of pattern. */ 288875b97b3SPeter Feiner bool simple_glob(const char *text, const char *pattern) 289875b97b3SPeter Feiner { 290875b97b3SPeter Feiner bool star_start = false; 291875b97b3SPeter Feiner bool star_end = false; 292875b97b3SPeter Feiner size_t n = strlen(pattern); 293875b97b3SPeter Feiner char copy[n + 1]; 294875b97b3SPeter Feiner 295875b97b3SPeter Feiner if (pattern[0] == '*') { 296875b97b3SPeter Feiner pattern += 1; 297875b97b3SPeter Feiner n -= 1; 298875b97b3SPeter Feiner star_start = true; 299875b97b3SPeter Feiner } 300875b97b3SPeter Feiner 301875b97b3SPeter Feiner strcpy(copy, pattern); 302875b97b3SPeter Feiner 303875b97b3SPeter Feiner if (n > 0 && pattern[n - 1] == '*') { 304875b97b3SPeter Feiner n -= 1; 305875b97b3SPeter Feiner copy[n] = '\0'; 306875b97b3SPeter Feiner star_end = true; 307875b97b3SPeter Feiner } 308875b97b3SPeter Feiner 309875b97b3SPeter Feiner if (star_start && star_end) 310875b97b3SPeter Feiner return strstr(text, copy); 311875b97b3SPeter Feiner 312875b97b3SPeter Feiner if (star_end) 313875b97b3SPeter Feiner return strstr(text, copy) == text; 314875b97b3SPeter Feiner 315875b97b3SPeter Feiner if (star_start) { 316875b97b3SPeter Feiner size_t text_len = strlen(text); 317875b97b3SPeter Feiner const char *suffix; 318875b97b3SPeter Feiner 319875b97b3SPeter Feiner if (n > text_len) 320875b97b3SPeter Feiner return false; 321875b97b3SPeter Feiner suffix = text + text_len - n; 322875b97b3SPeter Feiner return !strcmp(suffix, copy); 323875b97b3SPeter Feiner } 324875b97b3SPeter Feiner 325875b97b3SPeter Feiner return !strcmp(text, copy); 326875b97b3SPeter Feiner } 327