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"
95927d1c2SAndrew Jones #include "ctype.h"
10b5501ed0SNikos Nikoleris #include "stdlib.h"
11b5501ed0SNikos Nikoleris #include "linux/compiler.h"
127d36db35SAvi Kivity
strlen(const char * buf)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
strnlen(const char * buf,size_t maxlen)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
strcat(char * dest,const char * src)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
strcpy(char * dest,const char * src)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
strncmp(const char * a,const char * b,size_t n)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ář
strncasecmp(const char * a,const char * b,size_t n)57*24aec76aSAndrew Jones int strncasecmp(const char *a, const char *b, size_t n)
58*24aec76aSAndrew Jones {
59*24aec76aSAndrew Jones for (; n--; ++a, ++b)
60*24aec76aSAndrew Jones if (tolower(*a) != tolower(*b) || *a == '\0')
61*24aec76aSAndrew Jones return tolower(*a) - tolower(*b);
62*24aec76aSAndrew Jones
63*24aec76aSAndrew Jones return 0;
64*24aec76aSAndrew Jones }
65*24aec76aSAndrew Jones
strcmp(const char * a,const char * b)6669da6c87SAvi Kivity int strcmp(const char *a, const char *b)
6769da6c87SAvi Kivity {
684fd53297SRadim Krčmář return strncmp(a, b, SIZE_MAX);
6969da6c87SAvi Kivity }
7069da6c87SAvi Kivity
strcasecmp(const char * a,const char * b)71*24aec76aSAndrew Jones int strcasecmp(const char *a, const char *b)
72*24aec76aSAndrew Jones {
73*24aec76aSAndrew Jones return strncasecmp(a, b, SIZE_MAX);
74*24aec76aSAndrew Jones }
75*24aec76aSAndrew Jones
strchr(const char * s,int c)76782ebe33SAndrew Jones char *strchr(const char *s, int c)
77782ebe33SAndrew Jones {
78782ebe33SAndrew Jones while (*s != (char)c)
79782ebe33SAndrew Jones if (*s++ == '\0')
80782ebe33SAndrew Jones return NULL;
81782ebe33SAndrew Jones return (char *)s;
82782ebe33SAndrew Jones }
83782ebe33SAndrew Jones
strrchr(const char * s,int c)84b5501ed0SNikos Nikoleris char *strrchr(const char *s, int c)
85b5501ed0SNikos Nikoleris {
86b5501ed0SNikos Nikoleris const char *last = NULL;
87b5501ed0SNikos Nikoleris do {
88b5501ed0SNikos Nikoleris if (*s == (char)c)
89b5501ed0SNikos Nikoleris last = s;
90b5501ed0SNikos Nikoleris } while (*s++);
91b5501ed0SNikos Nikoleris return (char *)last;
92b5501ed0SNikos Nikoleris }
93b5501ed0SNikos Nikoleris
strchrnul(const char * s,int c)94546914b4SNikos Nikoleris char *strchrnul(const char *s, int c)
95546914b4SNikos Nikoleris {
96546914b4SNikos Nikoleris while (*s && *s != (char)c)
97546914b4SNikos Nikoleris s++;
98546914b4SNikos Nikoleris return (char *)s;
99546914b4SNikos Nikoleris }
100546914b4SNikos Nikoleris
strstr(const char * s1,const char * s2)10153da5cc0SAndrew Jones char *strstr(const char *s1, const char *s2)
10253da5cc0SAndrew Jones {
10353da5cc0SAndrew Jones size_t l1, l2;
10453da5cc0SAndrew Jones
10553da5cc0SAndrew Jones l2 = strlen(s2);
10653da5cc0SAndrew Jones if (!l2)
10753da5cc0SAndrew Jones return (char *)s1;
10853da5cc0SAndrew Jones l1 = strlen(s1);
10953da5cc0SAndrew Jones while (l1 >= l2) {
11053da5cc0SAndrew Jones l1--;
11153da5cc0SAndrew Jones if (!memcmp(s1, s2, l2))
11253da5cc0SAndrew Jones return (char *)s1;
11353da5cc0SAndrew Jones s1++;
11453da5cc0SAndrew Jones }
11553da5cc0SAndrew Jones return NULL;
11653da5cc0SAndrew Jones }
11753da5cc0SAndrew Jones
memset(void * s,int c,size_t n)1187d36db35SAvi Kivity void *memset(void *s, int c, size_t n)
1197d36db35SAvi Kivity {
1207d36db35SAvi Kivity size_t i;
1217d36db35SAvi Kivity char *a = s;
1227d36db35SAvi Kivity
1237d36db35SAvi Kivity for (i = 0; i < n; ++i)
1247d36db35SAvi Kivity a[i] = c;
1257d36db35SAvi Kivity
1267d36db35SAvi Kivity return s;
1277d36db35SAvi Kivity }
1281b708e8cSJason Wang
memcpy(void * dest,const void * src,size_t n)1298d68030eSArthur Chunqi Li void *memcpy(void *dest, const void *src, size_t n)
1308d68030eSArthur Chunqi Li {
1318d68030eSArthur Chunqi Li size_t i;
1328d68030eSArthur Chunqi Li char *a = dest;
1338d68030eSArthur Chunqi Li const char *b = src;
1348d68030eSArthur Chunqi Li
1358d68030eSArthur Chunqi Li for (i = 0; i < n; ++i)
1368d68030eSArthur Chunqi Li a[i] = b[i];
1378d68030eSArthur Chunqi Li
1388d68030eSArthur Chunqi Li return dest;
1398d68030eSArthur Chunqi Li }
1408d68030eSArthur Chunqi Li
memcmp(const void * s1,const void * s2,size_t n)141782ebe33SAndrew Jones int memcmp(const void *s1, const void *s2, size_t n)
142782ebe33SAndrew Jones {
143782ebe33SAndrew Jones const unsigned char *a = s1, *b = s2;
144782ebe33SAndrew Jones int ret = 0;
145782ebe33SAndrew Jones
146782ebe33SAndrew Jones while (n--) {
147782ebe33SAndrew Jones ret = *a - *b;
148782ebe33SAndrew Jones if (ret)
149782ebe33SAndrew Jones break;
150782ebe33SAndrew Jones ++a, ++b;
151782ebe33SAndrew Jones }
152782ebe33SAndrew Jones return ret;
153782ebe33SAndrew Jones }
154782ebe33SAndrew Jones
memmove(void * dest,const void * src,size_t n)155782ebe33SAndrew Jones void *memmove(void *dest, const void *src, size_t n)
156782ebe33SAndrew Jones {
157782ebe33SAndrew Jones const unsigned char *s = src;
158782ebe33SAndrew Jones unsigned char *d = dest;
159782ebe33SAndrew Jones
160782ebe33SAndrew Jones if (d <= s) {
161782ebe33SAndrew Jones while (n--)
162782ebe33SAndrew Jones *d++ = *s++;
163782ebe33SAndrew Jones } else {
164782ebe33SAndrew Jones d += n, s += n;
165782ebe33SAndrew Jones while (n--)
166782ebe33SAndrew Jones *--d = *--s;
167782ebe33SAndrew Jones }
168782ebe33SAndrew Jones return dest;
169782ebe33SAndrew Jones }
170782ebe33SAndrew Jones
memchr(const void * s,int c,size_t n)171782ebe33SAndrew Jones void *memchr(const void *s, int c, size_t n)
172782ebe33SAndrew Jones {
173782ebe33SAndrew Jones const unsigned char *str = s, chr = (unsigned char)c;
174782ebe33SAndrew Jones
175782ebe33SAndrew Jones while (n--)
176782ebe33SAndrew Jones if (*str++ == chr)
177782ebe33SAndrew Jones return (void *)(str - 1);
178782ebe33SAndrew Jones return NULL;
179782ebe33SAndrew Jones }
180782ebe33SAndrew Jones
__strtoll(const char * nptr,char ** endptr,int base,bool is_signed,bool is_longlong)1817f1ca26cSAndrew Jones static unsigned long long __strtoll(const char *nptr, char **endptr,
1820e981298SAndrew Jones int base, bool is_signed, bool is_longlong)
1830e981298SAndrew Jones {
1847f1ca26cSAndrew Jones unsigned long long ull = 0;
185b5501ed0SNikos Nikoleris const char *s = nptr;
1861b708e8cSJason Wang int neg, c;
1871b708e8cSJason Wang
188b5501ed0SNikos Nikoleris assert(base == 0 || (base >= 2 && base <= 36));
189b5501ed0SNikos Nikoleris
190b5501ed0SNikos Nikoleris while (isspace(*s))
1911b708e8cSJason Wang s++;
192b5501ed0SNikos Nikoleris
1931b708e8cSJason Wang if (*s == '-') {
1941b708e8cSJason Wang neg = 1;
1951b708e8cSJason Wang s++;
1961b708e8cSJason Wang } else {
1971b708e8cSJason Wang neg = 0;
1981b708e8cSJason Wang if (*s == '+')
1991b708e8cSJason Wang s++;
2001b708e8cSJason Wang }
2011b708e8cSJason Wang
202b5501ed0SNikos Nikoleris if (base == 0 || base == 16) {
203b5501ed0SNikos Nikoleris if (*s == '0') {
204b5501ed0SNikos Nikoleris s++;
205b5501ed0SNikos Nikoleris if (*s == 'x' || *s == 'X') {
206b5501ed0SNikos Nikoleris s++;
207b5501ed0SNikos Nikoleris base = 16;
208b5501ed0SNikos Nikoleris } else if (base == 0)
209b5501ed0SNikos Nikoleris base = 8;
210b5501ed0SNikos Nikoleris } else if (base == 0)
211b5501ed0SNikos Nikoleris base = 10;
212b5501ed0SNikos Nikoleris }
213b5501ed0SNikos Nikoleris
2141b708e8cSJason Wang while (*s) {
215b5501ed0SNikos Nikoleris if (*s >= '0' && *s < '0' + base && *s <= '9')
2161b708e8cSJason Wang c = *s - '0';
217b5501ed0SNikos Nikoleris else if (*s >= 'a' && *s < 'a' + base - 10)
218b5501ed0SNikos Nikoleris c = *s - 'a' + 10;
219b5501ed0SNikos Nikoleris else if (*s >= 'A' && *s < 'A' + base - 10)
220b5501ed0SNikos Nikoleris c = *s - 'A' + 10;
221b5501ed0SNikos Nikoleris else
222b5501ed0SNikos Nikoleris break;
223b5501ed0SNikos Nikoleris
2247f1ca26cSAndrew Jones if (!is_longlong) {
225b5501ed0SNikos Nikoleris if (is_signed) {
2267f1ca26cSAndrew Jones long sl = (long)ull;
2277f1ca26cSAndrew Jones assert(!check_mul_overflow(sl, base));
2287f1ca26cSAndrew Jones assert(!check_add_overflow(sl * base, c));
229b5501ed0SNikos Nikoleris } else {
2307f1ca26cSAndrew Jones unsigned long ul = (unsigned long)ull;
2317f1ca26cSAndrew Jones assert(!check_mul_overflow(ul, base));
2327f1ca26cSAndrew Jones assert(!check_add_overflow(ul * base, c));
2337f1ca26cSAndrew Jones }
2347f1ca26cSAndrew Jones } else {
2357f1ca26cSAndrew Jones if (is_signed) {
2367f1ca26cSAndrew Jones long long sll = (long long)ull;
2377f1ca26cSAndrew Jones assert(!check_mul_overflow(sll, base));
2387f1ca26cSAndrew Jones assert(!check_add_overflow(sll * base, c));
2397f1ca26cSAndrew Jones } else {
2407f1ca26cSAndrew Jones assert(!check_mul_overflow(ull, base));
2417f1ca26cSAndrew Jones assert(!check_add_overflow(ull * base, c));
2427f1ca26cSAndrew Jones }
243b5501ed0SNikos Nikoleris }
244b5501ed0SNikos Nikoleris
2457f1ca26cSAndrew Jones ull = ull * base + c;
2461b708e8cSJason Wang s++;
2471b708e8cSJason Wang }
2481b708e8cSJason Wang
2491b708e8cSJason Wang if (neg)
2507f1ca26cSAndrew Jones ull = -ull;
2511b708e8cSJason Wang
252b5501ed0SNikos Nikoleris if (endptr)
253b5501ed0SNikos Nikoleris *endptr = (char *)s;
254b5501ed0SNikos Nikoleris
2557f1ca26cSAndrew Jones return ull;
2561b708e8cSJason Wang }
25769205bf1SAndrew Jones
strtol(const char * nptr,char ** endptr,int base)258b5501ed0SNikos Nikoleris long int strtol(const char *nptr, char **endptr, int base)
259b5501ed0SNikos Nikoleris {
2607f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, true, false);
261b5501ed0SNikos Nikoleris }
262b5501ed0SNikos Nikoleris
strtoul(const char * nptr,char ** endptr,int base)263b5501ed0SNikos Nikoleris unsigned long int strtoul(const char *nptr, char **endptr, int base)
264b5501ed0SNikos Nikoleris {
2657f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, false, false);
2667f1ca26cSAndrew Jones }
2677f1ca26cSAndrew Jones
strtoll(const char * nptr,char ** endptr,int base)2687f1ca26cSAndrew Jones long long int strtoll(const char *nptr, char **endptr, int base)
2697f1ca26cSAndrew Jones {
2707f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, true, true);
2717f1ca26cSAndrew Jones }
2727f1ca26cSAndrew Jones
strtoull(const char * nptr,char ** endptr,int base)2737f1ca26cSAndrew Jones unsigned long long int strtoull(const char *nptr, char **endptr, int base)
2747f1ca26cSAndrew Jones {
2757f1ca26cSAndrew Jones return __strtoll(nptr, endptr, base, false, true);
276b5501ed0SNikos Nikoleris }
277b5501ed0SNikos Nikoleris
atol(const char * ptr)278b5501ed0SNikos Nikoleris long atol(const char *ptr)
279b5501ed0SNikos Nikoleris {
280b5501ed0SNikos Nikoleris return strtol(ptr, NULL, 10);
281b5501ed0SNikos Nikoleris }
282b5501ed0SNikos Nikoleris
28369205bf1SAndrew Jones extern char **environ;
28469205bf1SAndrew Jones
getenv(const char * name)28569205bf1SAndrew Jones char *getenv(const char *name)
28669205bf1SAndrew Jones {
28769205bf1SAndrew Jones char **envp = environ, *delim;
2884837df6eSAndrew Jones int len;
28969205bf1SAndrew Jones
29069205bf1SAndrew Jones while (*envp) {
29169205bf1SAndrew Jones delim = strchr(*envp, '=');
2924837df6eSAndrew Jones assert(delim);
2934837df6eSAndrew Jones len = delim - *envp;
2944837df6eSAndrew Jones if (memcmp(name, *envp, len) == 0 && !name[len])
29569205bf1SAndrew Jones return delim + 1;
29669205bf1SAndrew Jones ++envp;
29769205bf1SAndrew Jones }
29869205bf1SAndrew Jones return NULL;
29969205bf1SAndrew Jones }
300875b97b3SPeter Feiner
301875b97b3SPeter Feiner /* Very simple glob matching. Allows '*' at beginning and end of pattern. */
simple_glob(const char * text,const char * pattern)302875b97b3SPeter Feiner bool simple_glob(const char *text, const char *pattern)
303875b97b3SPeter Feiner {
304875b97b3SPeter Feiner bool star_start = false;
305875b97b3SPeter Feiner bool star_end = false;
306875b97b3SPeter Feiner size_t n = strlen(pattern);
307875b97b3SPeter Feiner char copy[n + 1];
308875b97b3SPeter Feiner
309875b97b3SPeter Feiner if (pattern[0] == '*') {
310875b97b3SPeter Feiner pattern += 1;
311875b97b3SPeter Feiner n -= 1;
312875b97b3SPeter Feiner star_start = true;
313875b97b3SPeter Feiner }
314875b97b3SPeter Feiner
315875b97b3SPeter Feiner strcpy(copy, pattern);
316875b97b3SPeter Feiner
317875b97b3SPeter Feiner if (n > 0 && pattern[n - 1] == '*') {
318875b97b3SPeter Feiner n -= 1;
319875b97b3SPeter Feiner copy[n] = '\0';
320875b97b3SPeter Feiner star_end = true;
321875b97b3SPeter Feiner }
322875b97b3SPeter Feiner
323875b97b3SPeter Feiner if (star_start && star_end)
324875b97b3SPeter Feiner return strstr(text, copy);
325875b97b3SPeter Feiner
326875b97b3SPeter Feiner if (star_end)
327875b97b3SPeter Feiner return strstr(text, copy) == text;
328875b97b3SPeter Feiner
329875b97b3SPeter Feiner if (star_start) {
330875b97b3SPeter Feiner size_t text_len = strlen(text);
331875b97b3SPeter Feiner const char *suffix;
332875b97b3SPeter Feiner
333875b97b3SPeter Feiner if (n > text_len)
334875b97b3SPeter Feiner return false;
335875b97b3SPeter Feiner suffix = text + text_len - n;
336875b97b3SPeter Feiner return !strcmp(suffix, copy);
337875b97b3SPeter Feiner }
338875b97b3SPeter Feiner
339875b97b3SPeter Feiner return !strcmp(text, copy);
340875b97b3SPeter Feiner }
341