libc.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2015 Dale Weiler
  5. *
  6. * Standard C library for kernel
  7. *
  8. */
  9. #include <kernel/system.h>
  10. #include <limits.h>
  11. #define ALIGN (sizeof(size_t))
  12. #define ONES ((size_t)-1/UCHAR_MAX)
  13. #define HIGHS (ONES * (UCHAR_MAX/2+1))
  14. #define HASZERO(X) (((X)-ONES) & ~(X) & HIGHS)
  15. #define BITOP(A, B, OP) \
  16. ((A)[(size_t)(B)/(8*sizeof *(A))] OP (size_t)1<<((size_t)(B)%(8*sizeof *(A))))
  17. void * memcpy(void * restrict dest, const void * restrict src, size_t n) {
  18. asm volatile("cld; rep movsb"
  19. : "=c"((int){0})
  20. : "D"(dest), "S"(src), "c"(n)
  21. : "flags", "memory");
  22. return dest;
  23. }
  24. void * memset(void * dest, int c, size_t n) {
  25. asm volatile("cld; rep stosb"
  26. : "=c"((int){0})
  27. : "D"(dest), "a"(c), "c"(n)
  28. : "flags", "memory");
  29. return dest;
  30. }
  31. int memcmp(const void * vl, const void * vr, size_t n) {
  32. const unsigned char *l = vl;
  33. const unsigned char *r = vr;
  34. for (; n && *l == *r; n--, l++, r++);
  35. return n ? *l-*r : 0;
  36. }
  37. void * memchr(const void * src, int c, size_t n) {
  38. const unsigned char * s = src;
  39. c = (unsigned char)c;
  40. for (; ((uintptr_t)s & (ALIGN - 1)) && n && *s != c; s++, n--);
  41. if (n && *s != c) {
  42. const size_t * w;
  43. size_t k = ONES * c;
  44. for (w = (const void *)s; n >= sizeof(size_t) && !HASZERO(*w^k); w++, n -= sizeof(size_t));
  45. for (s = (const void *)w; n && *s != c; s++, n--);
  46. }
  47. return n ? (void *)s : 0;
  48. }
  49. void * memrchr(const void * m, int c, size_t n) {
  50. const unsigned char * s = m;
  51. c = (unsigned char)c;
  52. while (n--) {
  53. if (s[n] == c) {
  54. return (void*)(s+n);
  55. }
  56. }
  57. return 0;
  58. }
  59. void * memmove(void * dest, const void * src, size_t n) {
  60. char * d = dest;
  61. const char * s = src;
  62. if (d==s) {
  63. return d;
  64. }
  65. if (s+n <= d || d+n <= s) {
  66. return memcpy(d, s, n);
  67. }
  68. if (d<s) {
  69. if ((uintptr_t)s % sizeof(size_t) == (uintptr_t)d % sizeof(size_t)) {
  70. while ((uintptr_t)d % sizeof(size_t)) {
  71. if (!n--) {
  72. return dest;
  73. }
  74. *d++ = *s++;
  75. }
  76. for (; n >= sizeof(size_t); n -= sizeof(size_t), d += sizeof(size_t), s += sizeof(size_t)) {
  77. *(size_t *)d = *(size_t *)s;
  78. }
  79. }
  80. for (; n; n--) {
  81. *d++ = *s++;
  82. }
  83. } else {
  84. if ((uintptr_t)s % sizeof(size_t) == (uintptr_t)d % sizeof(size_t)) {
  85. while ((uintptr_t)(d+n) % sizeof(size_t)) {
  86. if (!n--) {
  87. return dest;
  88. }
  89. d[n] = s[n];
  90. }
  91. while (n >= sizeof(size_t)) {
  92. n -= sizeof(size_t);
  93. *(size_t *)(d+n) = *(size_t *)(s+n);
  94. }
  95. }
  96. while (n) {
  97. n--;
  98. d[n] = s[n];
  99. }
  100. }
  101. return dest;
  102. }
  103. int strcmp(const char * l, const char * r) {
  104. for (; *l == *r && *l; l++, r++);
  105. return *(unsigned char *)l - *(unsigned char *)r;
  106. }
  107. size_t strlen(const char * s) {
  108. const char * a = s;
  109. const size_t * w;
  110. for (; (uintptr_t)s % ALIGN; s++) {
  111. if (!*s) {
  112. return s-a;
  113. }
  114. }
  115. for (w = (const void *)s; !HASZERO(*w); w++);
  116. for (s = (const void *)w; *s; s++);
  117. return s-a;
  118. }
  119. char * strdup(const char * s) {
  120. size_t l = strlen(s);
  121. return memcpy(malloc(l+1), s, l+1);
  122. }
  123. char * stpcpy(char * restrict d, const char * restrict s) {
  124. size_t * wd;
  125. const size_t * ws;
  126. if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
  127. for (; (uintptr_t)s % ALIGN; s++, d++) {
  128. if (!(*d = *s)) {
  129. return d;
  130. }
  131. }
  132. wd = (void *)d;
  133. ws = (const void *)s;
  134. for (; !HASZERO(*ws); *wd++ = *ws++);
  135. d = (void *)wd;
  136. s = (const void *)ws;
  137. }
  138. for (; (*d=*s); s++, d++);
  139. return d;
  140. }
  141. char * strcpy(char * restrict dest, const char * restrict src) {
  142. stpcpy(dest, src);
  143. return dest;
  144. }
  145. size_t strspn(const char * s, const char * c) {
  146. const char * a = s;
  147. size_t byteset[32/sizeof(size_t)] = { 0 };
  148. if (!c[0]) {
  149. return 0;
  150. }
  151. if (!c[1]) {
  152. for (; *s == *c; s++);
  153. return s-a;
  154. }
  155. for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
  156. for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
  157. return s-a;
  158. }
  159. char * strchrnul(const char * s, int c) {
  160. size_t * w;
  161. size_t k;
  162. c = (unsigned char)c;
  163. if (!c) {
  164. return (char *)s + strlen(s);
  165. }
  166. for (; (uintptr_t)s % ALIGN; s++) {
  167. if (!*s || *(unsigned char *)s == c) {
  168. return (char *)s;
  169. }
  170. }
  171. k = ONES * c;
  172. for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
  173. for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
  174. return (char *)s;
  175. }
  176. char * strchr(const char * s, int c) {
  177. char *r = strchrnul(s, c);
  178. return *(unsigned char *)r == (unsigned char)c ? r : 0;
  179. }
  180. char * strrchr(const char * s, int c) {
  181. return memrchr(s, c, strlen(s) + 1);
  182. }
  183. size_t strcspn(const char * s, const char * c) {
  184. const char *a = s;
  185. if (c[0] && c[1]) {
  186. size_t byteset[32/sizeof(size_t)] = { 0 };
  187. for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
  188. for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
  189. return s-a;
  190. }
  191. return strchrnul(s, *c)-a;
  192. }
  193. char * strpbrk(const char * s, const char * b) {
  194. s += strcspn(s, b);
  195. return *s ? (char *)s : 0;
  196. }
  197. static char *strstr_2b(const unsigned char * h, const unsigned char * n) {
  198. uint16_t nw = n[0] << 8 | n[1];
  199. uint16_t hw = h[0] << 8 | h[1];
  200. for (h++; *h && hw != nw; hw = hw << 8 | *++h);
  201. return *h ? (char *)h-1 : 0;
  202. }
  203. static char *strstr_3b(const unsigned char * h, const unsigned char * n) {
  204. uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8;
  205. uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8;
  206. for (h += 2; *h && hw != nw; hw = (hw|*++h) << 8);
  207. return *h ? (char *)h-2 : 0;
  208. }
  209. static char *strstr_4b(const unsigned char * h, const unsigned char * n) {
  210. uint32_t nw = n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3];
  211. uint32_t hw = h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3];
  212. for (h += 3; *h && hw != nw; hw = hw << 8 | *++h);
  213. return *h ? (char *)h-3 : 0;
  214. }
  215. static char *strstr_twoway(const unsigned char * h, const unsigned char * n) {
  216. size_t mem;
  217. size_t mem0;
  218. size_t byteset[32 / sizeof(size_t)] = { 0 };
  219. size_t shift[256];
  220. size_t l;
  221. /* Computing length of needle and fill shift table */
  222. for (l = 0; n[l] && h[l]; l++) {
  223. BITOP(byteset, n[l], |=);
  224. shift[n[l]] = l+1;
  225. }
  226. if (n[l]) {
  227. return 0; /* hit the end of h */
  228. }
  229. /* Compute maximal suffix */
  230. size_t ip = -1;
  231. size_t jp = 0;
  232. size_t k = 1;
  233. size_t p = 1;
  234. while (jp+k<l) {
  235. if (n[ip+k] == n[jp+k]) {
  236. if (k == p) {
  237. jp += p;
  238. k = 1;
  239. } else {
  240. k++;
  241. }
  242. } else if (n[ip+k] > n[jp+k]) {
  243. jp += k;
  244. k = 1;
  245. p = jp - ip;
  246. } else {
  247. ip = jp++;
  248. k = p = 1;
  249. }
  250. }
  251. size_t ms = ip;
  252. size_t p0 = p;
  253. /* And with the opposite comparison */
  254. ip = -1;
  255. jp = 0;
  256. k = p = 1;
  257. while (jp+k<l) {
  258. if (n[ip+k] == n[jp+k]) {
  259. if (k == p) {
  260. jp += p;
  261. k = 1;
  262. } else {
  263. k++;
  264. }
  265. } else if (n[ip+k] < n[jp+k]) {
  266. jp += k;
  267. k = 1;
  268. p = jp - ip;
  269. } else {
  270. ip = jp++;
  271. k = p = 1;
  272. }
  273. }
  274. if (ip+1 > ms+1) {
  275. ms = ip;
  276. } else {
  277. p = p0;
  278. }
  279. /* Periodic needle? */
  280. if (memcmp(n, n+p, ms+1)) {
  281. mem0 = 0;
  282. p = MAX(ms, l-ms-1) + 1;
  283. } else {
  284. mem0 = l-p;
  285. }
  286. mem = 0;
  287. /* Initialize incremental end-of-haystack pointer */
  288. const unsigned char * z = h;
  289. /* Search loop */
  290. for (;;) {
  291. /* Update incremental end-of-haystack pointer */
  292. if ((size_t)(z-h) < l) {
  293. /* Fast estimate for MIN(l,63) */
  294. size_t grow = l | 63;
  295. const unsigned char *z2 = memchr(z, 0, grow);
  296. if (z2) {
  297. z = z2;
  298. if ((size_t)(z-h) < l) {
  299. return 0;
  300. }
  301. } else {
  302. z += grow;
  303. }
  304. }
  305. /* Check last byte first; advance by shift on mismatch */
  306. if (BITOP(byteset, h[l-1], &)) {
  307. k = l-shift[h[l-1]];
  308. if (k) {
  309. if (mem0 && mem && k < p) k = l-p;
  310. h += k;
  311. mem = 0;
  312. continue;
  313. }
  314. } else {
  315. h += l;
  316. mem = 0;
  317. continue;
  318. }
  319. /* Compare right half */
  320. for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
  321. if (n[k]) {
  322. h += k-ms;
  323. mem = 0;
  324. continue;
  325. }
  326. /* Compare left half */
  327. for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
  328. if (k <= mem) {
  329. return (char *)h;
  330. }
  331. h += p;
  332. mem = mem0;
  333. }
  334. }
  335. char *strstr(const char * h, const char * n) {
  336. /* Return immediately on empty needle */
  337. if (!n[0]) {
  338. return (char *)h;
  339. }
  340. /* Use faster algorithms for short needles */
  341. h = strchr(h, *n);
  342. if (!h || !n[1]) {
  343. return (char *)h;
  344. }
  345. if (!h[1]) return 0;
  346. if (!n[2]) return strstr_2b((void *)h, (void *)n);
  347. if (!h[2]) return 0;
  348. if (!n[3]) return strstr_3b((void *)h, (void *)n);
  349. if (!h[3]) return 0;
  350. if (!n[4]) return strstr_4b((void *)h, (void *)n);
  351. /* Two-way on large needles */
  352. return strstr_twoway((void *)h, (void *)n);
  353. }
  354. static inline int isdigit(int ch) {
  355. return (unsigned int)ch-'0' < 10;
  356. }
  357. static inline int isspace(int ch) {
  358. return ch == ' ' || (unsigned int)ch-'\t' < 5;
  359. }
  360. int atoi(const char * s) {
  361. int n = 0;
  362. int neg = 0;
  363. while (isspace(*s)) {
  364. s++;
  365. }
  366. switch (*s) {
  367. case '-':
  368. neg = 1;
  369. /* Fallthrough is intentional here */
  370. case '+':
  371. s++;
  372. }
  373. while (isdigit(*s)) {
  374. n = 10*n - (*s++ - '0');
  375. }
  376. /* The sign order may look incorrect here but this is correct as n is calculated
  377. * as a negative number to avoid overflow on INT_MAX.
  378. */
  379. return neg ? n : -n;
  380. }
  381. char * strtok_r(char * str, const char * delim, char ** saveptr) {
  382. char * token;
  383. if (str == NULL) {
  384. str = *saveptr;
  385. }
  386. str += strspn(str, delim);
  387. if (*str == '\0') {
  388. *saveptr = str;
  389. return NULL;
  390. }
  391. token = str;
  392. str = strpbrk(token, delim);
  393. if (str == NULL) {
  394. *saveptr = (char *)lfind(token, '\0');
  395. } else {
  396. *str = '\0';
  397. *saveptr = str + 1;
  398. }
  399. return token;
  400. }