1 /* 2 * libc string functions 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU Library General Public License version 2. 6 */ 7 8 #include "libcflat.h" 9 #include "stdlib.h" 10 #include "linux/compiler.h" 11 12 size_t strlen(const char *buf) 13 { 14 size_t len = 0; 15 16 while (*buf++) 17 ++len; 18 return len; 19 } 20 21 size_t strnlen(const char *buf, size_t maxlen) 22 { 23 const char *sc; 24 25 for (sc = buf; maxlen-- && *sc != '\0'; ++sc) 26 /* nothing */; 27 return sc - buf; 28 } 29 30 char *strcat(char *dest, const char *src) 31 { 32 char *p = dest; 33 34 while (*p) 35 ++p; 36 while ((*p++ = *src++) != 0) 37 ; 38 return dest; 39 } 40 41 char *strcpy(char *dest, const char *src) 42 { 43 *dest = 0; 44 return strcat(dest, src); 45 } 46 47 int strncmp(const char *a, const char *b, size_t n) 48 { 49 for (; n--; ++a, ++b) 50 if (*a != *b || *a == '\0') 51 return *a - *b; 52 53 return 0; 54 } 55 56 int strcmp(const char *a, const char *b) 57 { 58 return strncmp(a, b, SIZE_MAX); 59 } 60 61 char *strchr(const char *s, int c) 62 { 63 while (*s != (char)c) 64 if (*s++ == '\0') 65 return NULL; 66 return (char *)s; 67 } 68 69 char *strrchr(const char *s, int c) 70 { 71 const char *last = NULL; 72 do { 73 if (*s == (char)c) 74 last = s; 75 } while (*s++); 76 return (char *)last; 77 } 78 79 char *strstr(const char *s1, const char *s2) 80 { 81 size_t l1, l2; 82 83 l2 = strlen(s2); 84 if (!l2) 85 return (char *)s1; 86 l1 = strlen(s1); 87 while (l1 >= l2) { 88 l1--; 89 if (!memcmp(s1, s2, l2)) 90 return (char *)s1; 91 s1++; 92 } 93 return NULL; 94 } 95 96 void *memset(void *s, int c, size_t n) 97 { 98 size_t i; 99 char *a = s; 100 101 for (i = 0; i < n; ++i) 102 a[i] = c; 103 104 return s; 105 } 106 107 void *memcpy(void *dest, const void *src, size_t n) 108 { 109 size_t i; 110 char *a = dest; 111 const char *b = src; 112 113 for (i = 0; i < n; ++i) 114 a[i] = b[i]; 115 116 return dest; 117 } 118 119 int memcmp(const void *s1, const void *s2, size_t n) 120 { 121 const unsigned char *a = s1, *b = s2; 122 int ret = 0; 123 124 while (n--) { 125 ret = *a - *b; 126 if (ret) 127 break; 128 ++a, ++b; 129 } 130 return ret; 131 } 132 133 void *memmove(void *dest, const void *src, size_t n) 134 { 135 const unsigned char *s = src; 136 unsigned char *d = dest; 137 138 if (d <= s) { 139 while (n--) 140 *d++ = *s++; 141 } else { 142 d += n, s += n; 143 while (n--) 144 *--d = *--s; 145 } 146 return dest; 147 } 148 149 void *memchr(const void *s, int c, size_t n) 150 { 151 const unsigned char *str = s, chr = (unsigned char)c; 152 153 while (n--) 154 if (*str++ == chr) 155 return (void *)(str - 1); 156 return NULL; 157 } 158 159 static int isspace(int c) 160 { 161 return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f'; 162 } 163 164 static unsigned long __strtol(const char *nptr, char **endptr, 165 int base, bool is_signed) { 166 unsigned long acc = 0; 167 const char *s = nptr; 168 int neg, c; 169 170 assert(base == 0 || (base >= 2 && base <= 36)); 171 172 while (isspace(*s)) 173 s++; 174 175 if (*s == '-') { 176 neg = 1; 177 s++; 178 } else { 179 neg = 0; 180 if (*s == '+') 181 s++; 182 } 183 184 if (base == 0 || base == 16) { 185 if (*s == '0') { 186 s++; 187 if (*s == 'x' || *s == 'X') { 188 s++; 189 base = 16; 190 } else if (base == 0) 191 base = 8; 192 } else if (base == 0) 193 base = 10; 194 } 195 196 while (*s) { 197 if (*s >= '0' && *s < '0' + base && *s <= '9') 198 c = *s - '0'; 199 else if (*s >= 'a' && *s < 'a' + base - 10) 200 c = *s - 'a' + 10; 201 else if (*s >= 'A' && *s < 'A' + base - 10) 202 c = *s - 'A' + 10; 203 else 204 break; 205 206 if (is_signed) { 207 long sacc = (long)acc; 208 assert(!check_mul_overflow(sacc, base)); 209 assert(!check_add_overflow(sacc * base, c)); 210 } else { 211 assert(!check_mul_overflow(acc, base)); 212 assert(!check_add_overflow(acc * base, c)); 213 } 214 215 acc = acc * base + c; 216 s++; 217 } 218 219 if (neg) 220 acc = -acc; 221 222 if (endptr) 223 *endptr = (char *)s; 224 225 return acc; 226 } 227 228 long int strtol(const char *nptr, char **endptr, int base) 229 { 230 return __strtol(nptr, endptr, base, true); 231 } 232 233 unsigned long int strtoul(const char *nptr, char **endptr, int base) 234 { 235 return __strtol(nptr, endptr, base, false); 236 } 237 238 long atol(const char *ptr) 239 { 240 return strtol(ptr, NULL, 10); 241 } 242 243 extern char **environ; 244 245 char *getenv(const char *name) 246 { 247 char **envp = environ, *delim; 248 int len; 249 250 while (*envp) { 251 delim = strchr(*envp, '='); 252 assert(delim); 253 len = delim - *envp; 254 if (memcmp(name, *envp, len) == 0 && !name[len]) 255 return delim + 1; 256 ++envp; 257 } 258 return NULL; 259 } 260 261 /* Very simple glob matching. Allows '*' at beginning and end of pattern. */ 262 bool simple_glob(const char *text, const char *pattern) 263 { 264 bool star_start = false; 265 bool star_end = false; 266 size_t n = strlen(pattern); 267 char copy[n + 1]; 268 269 if (pattern[0] == '*') { 270 pattern += 1; 271 n -= 1; 272 star_start = true; 273 } 274 275 strcpy(copy, pattern); 276 277 if (n > 0 && pattern[n - 1] == '*') { 278 n -= 1; 279 copy[n] = '\0'; 280 star_end = true; 281 } 282 283 if (star_start && star_end) 284 return strstr(text, copy); 285 286 if (star_end) 287 return strstr(text, copy) == text; 288 289 if (star_start) { 290 size_t text_len = strlen(text); 291 const char *suffix; 292 293 if (n > text_len) 294 return false; 295 suffix = text + text_len - n; 296 return !strcmp(suffix, copy); 297 } 298 299 return !strcmp(text, copy); 300 } 301