stdio.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. #include <assert.h>
  2. #include <devutil.h>
  3. #include <fcntl.h>
  4. #include <list.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <stdarg.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <priv-vars.h>
  12. static inline int __feof_or_error(FILE* stream)
  13. {
  14. return !!(stream->flags & (FILE_ERROR | FILE_EOF));
  15. }
  16. // where n is in the range of [0, 9]
  17. static inline char d_to_c(int32_t n)
  18. {
  19. return '0' + n;
  20. }
  21. // where n is between 0 and 15
  22. // base is either 'a' of 'A',
  23. // depending on you want capitalized
  24. // or not
  25. static inline char hex_to_c(int32_t n, char base)
  26. {
  27. if (n < 10) {
  28. // n belongs to [0, 9]
  29. return d_to_c(n);
  30. } else {
  31. // n belongs to [10, 15]
  32. return base + (n - 10);
  33. }
  34. }
  35. static inline char x_to_c(int32_t n)
  36. {
  37. return hex_to_c(n, 'a');
  38. }
  39. static inline char X_to_c(int32_t n)
  40. {
  41. return hex_to_c(n, 'A');
  42. }
  43. // this will check if there is still free space
  44. // in the buffer. if so, push the char into it,
  45. // change the value of buf_size and move pointer
  46. // forward
  47. //
  48. // x: char* buf
  49. // y: size_t buf_size
  50. // z: char c
  51. #define do_write_if_free(x, y, z) \
  52. if ((y) > 1) { \
  53. *((x)++) = (z); \
  54. --(y); \
  55. }
  56. static inline ssize_t
  57. snprint_decimal32(
  58. char* buf,
  59. size_t buf_size,
  60. int32_t num)
  61. {
  62. ssize_t n_write = 0;
  63. if (num < 0) {
  64. do_write_if_free(buf, buf_size, '-');
  65. ++n_write;
  66. num *= (-1);
  67. }
  68. char* orig_buf = buf;
  69. do {
  70. do_write_if_free(buf, buf_size, d_to_c(num % 10));
  71. num /= 10;
  72. ++n_write;
  73. } while (num != 0);
  74. // prepend trailing '\0'
  75. if (buf_size > 0)
  76. *buf = 0x00;
  77. // move buf pointer to the last digit of number
  78. --buf;
  79. // reverse output
  80. while (orig_buf < buf) {
  81. char c = *buf;
  82. *buf = *orig_buf;
  83. *orig_buf = c;
  84. --buf;
  85. ++orig_buf;
  86. }
  87. return n_write;
  88. }
  89. static inline ssize_t
  90. snprint_decimal64(
  91. char* buf,
  92. size_t buf_size,
  93. int64_t num)
  94. {
  95. ssize_t n_write = 0;
  96. if (num < 0) {
  97. do_write_if_free(buf, buf_size, '-');
  98. ++n_write;
  99. num *= (-1);
  100. }
  101. char* orig_buf = buf;
  102. do {
  103. do_write_if_free(buf, buf_size, d_to_c(num % 10));
  104. num /= 10;
  105. ++n_write;
  106. } while (num != 0);
  107. // prepend trailing '\0'
  108. if (buf_size > 0)
  109. *buf = 0x00;
  110. // move buf pointer to the last digit of number
  111. --buf;
  112. // reverse output
  113. while (orig_buf < buf) {
  114. char c = *buf;
  115. *buf = *orig_buf;
  116. *orig_buf = c;
  117. --buf;
  118. ++orig_buf;
  119. }
  120. return n_write;
  121. }
  122. static inline ssize_t
  123. snprint_hex32(
  124. char* buf,
  125. size_t buf_size,
  126. uint32_t num,
  127. int32_t capitalized)
  128. {
  129. ssize_t n_write = 0;
  130. do_write_if_free(buf, buf_size, '0');
  131. if (capitalized) {
  132. do_write_if_free(buf, buf_size, 'X');
  133. } else {
  134. do_write_if_free(buf, buf_size, 'x');
  135. }
  136. n_write += 2;
  137. char* orig_buf = buf;
  138. do {
  139. if (capitalized) {
  140. do_write_if_free(buf, buf_size, X_to_c(num % 16));
  141. } else {
  142. do_write_if_free(buf, buf_size, x_to_c(num % 16));
  143. }
  144. num /= 16;
  145. ++n_write;
  146. } while (num != 0);
  147. // prepend trailing '\0'
  148. if (buf_size > 0)
  149. *buf = 0x00;
  150. // move buf pointer to the last digit of number
  151. --buf;
  152. // reverse output
  153. while (orig_buf < buf) {
  154. char c = *buf;
  155. *buf = *orig_buf;
  156. *orig_buf = c;
  157. --buf;
  158. ++orig_buf;
  159. }
  160. return n_write;
  161. }
  162. static inline ssize_t
  163. snprint_hex64(
  164. char* buf,
  165. size_t buf_size,
  166. uint64_t num,
  167. int32_t capitalized)
  168. {
  169. ssize_t n_write = 0;
  170. do_write_if_free(buf, buf_size, '0');
  171. if (capitalized) {
  172. do_write_if_free(buf, buf_size, 'X');
  173. } else {
  174. do_write_if_free(buf, buf_size, 'x');
  175. }
  176. n_write += 2;
  177. char* orig_buf = buf;
  178. do {
  179. if (capitalized) {
  180. do_write_if_free(buf, buf_size, X_to_c(num % 16));
  181. } else {
  182. do_write_if_free(buf, buf_size, x_to_c(num % 16));
  183. }
  184. num /= 16;
  185. ++n_write;
  186. } while (num != 0);
  187. // prepend trailing '\0'
  188. if (buf_size > 0)
  189. *buf = 0x00;
  190. // move buf pointer to the last digit of number
  191. --buf;
  192. // reverse output
  193. while (orig_buf < buf) {
  194. char c = *buf;
  195. *buf = *orig_buf;
  196. *orig_buf = c;
  197. --buf;
  198. ++orig_buf;
  199. }
  200. return n_write;
  201. }
  202. static inline ssize_t
  203. snprint_char(
  204. char* buf,
  205. size_t buf_size,
  206. char c)
  207. {
  208. if (buf_size > 1)
  209. *buf = c;
  210. return sizeof(c);
  211. }
  212. int snprintf(char* buf, size_t bufsize, const char* fmt, ...)
  213. {
  214. va_list lst;
  215. va_start(lst, fmt);
  216. int ret = vsnprintf(buf, bufsize, fmt, lst);
  217. va_end(lst);
  218. return ret;
  219. }
  220. int vsnprintf(char* buf, size_t buf_size, const char* fmt, va_list arg)
  221. {
  222. ssize_t n_write = 0;
  223. for (char c; (c = *fmt) != 0x00; ++fmt) {
  224. if (c == '%') {
  225. size_t n_tmp_write = 0;
  226. switch (*(++fmt)) {
  227. // int
  228. case 'd':
  229. n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, int));
  230. break;
  231. case 'x':
  232. n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 0);
  233. break;
  234. case 'X':
  235. n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 1);
  236. break;
  237. // long decimal
  238. case 'l':
  239. switch (*(++fmt)) {
  240. // long long aka int64
  241. case 'l':
  242. switch (*(++fmt)) {
  243. case 'd':
  244. n_tmp_write = snprint_decimal64(buf, buf_size, va_arg(arg, long long));
  245. break;
  246. case 'x':
  247. n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 0);
  248. break;
  249. case 'X':
  250. n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 1);
  251. break;
  252. }
  253. break;
  254. // long int aka int32
  255. case 'd':
  256. n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, long));
  257. break;
  258. case 'x':
  259. n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 0);
  260. break;
  261. case 'X':
  262. n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 1);
  263. break;
  264. }
  265. break;
  266. // c string
  267. case 's':
  268. n_tmp_write = snprintf(buf, buf_size, va_arg(arg, const char*));
  269. break;
  270. // int8 char
  271. case 'c':
  272. n_tmp_write = snprint_char(buf, buf_size, va_arg(arg, int));
  273. break;
  274. // pointer
  275. case 'p':
  276. #ifdef __32bit_system
  277. n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, size_t), 0);
  278. #else
  279. n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, size_t), 0);
  280. #endif
  281. break;
  282. default:
  283. n_tmp_write = snprint_char(buf, buf_size, *(fmt - 1));
  284. break;
  285. }
  286. n_write += n_tmp_write;
  287. if (buf_size > 1) {
  288. if (buf_size > n_tmp_write) {
  289. buf += n_tmp_write;
  290. buf_size -= n_tmp_write;
  291. } else {
  292. // no enough space
  293. // shrink buf_size to one
  294. buf += (buf_size - 1);
  295. buf_size = 1;
  296. }
  297. }
  298. } else {
  299. ++n_write;
  300. do_write_if_free(buf, buf_size, c);
  301. }
  302. }
  303. if (buf_size > 0)
  304. *buf = 0x00;
  305. return n_write;
  306. }
  307. int sprintf(char* buf, const char* fmt, ...)
  308. {
  309. va_list lst;
  310. va_start(lst, fmt);
  311. int ret = vsnprintf(buf, __SIZE_MAX__, fmt, lst);
  312. va_end(lst);
  313. return ret;
  314. }
  315. int puts(const char* str)
  316. {
  317. return fputs(str, stdout);
  318. }
  319. char* gets(char* buf)
  320. {
  321. int c, num = 0;
  322. while ((c = getchar()) != EOF && c != '\n')
  323. buf[num++] = c;
  324. buf[num] = 0;
  325. if (c == EOF)
  326. return NULL;
  327. return buf;
  328. }
  329. int vfprintf_u32(uint32_t num, FILE* stream)
  330. {
  331. if (num <= 9) {
  332. fputc(d_to_c(num), stream);
  333. return 1;
  334. }
  335. int ret = vfprintf_u32(num / 10, stream);
  336. fputc(d_to_c(num % 10), stream);
  337. return ret + 1;
  338. }
  339. int vfprintf_d32(int32_t num, FILE* stream)
  340. {
  341. if (num < 0) {
  342. fputc('-', stream);
  343. return vfprintf_u32(-num, stream) + 1;
  344. }
  345. return vfprintf_u32(num, stream);
  346. }
  347. int vfprintf_u64(uint64_t num, FILE* stream)
  348. {
  349. if (num <= 9) {
  350. fputc(d_to_c(num), stream);
  351. return 1;
  352. }
  353. int ret = vfprintf_u64(num / 10, stream);
  354. fputc(d_to_c(num % 10), stream);
  355. return ret + 1;
  356. }
  357. int vfprintf_d64(int64_t num, FILE* stream)
  358. {
  359. if (num < 0) {
  360. fputc('-', stream);
  361. return vfprintf_u64(-num, stream) + 1;
  362. }
  363. return vfprintf_u64(num, stream);
  364. }
  365. int vfprintf_x32(uint32_t num, int off, FILE* stream)
  366. {
  367. // print leading 0x
  368. if (off & 1) {
  369. --off;
  370. fputc('0', stream);
  371. fputc('X' + off, stream);
  372. return vfprintf_x32(num, off, stream) + 2;
  373. }
  374. if (num <= 15) {
  375. fputc(X_to_c(num) + off, stream);
  376. return 1;
  377. }
  378. int ret = vfprintf_x32(num >> 4, off, stream);
  379. fputc(X_to_c(num & 0xf) + off, stream);
  380. return ret + 1;
  381. }
  382. int vfprintf_x64(uint64_t num, int off, FILE* stream)
  383. {
  384. // print leading 0x
  385. if (off & 1) {
  386. --off;
  387. fputc('0', stream);
  388. fputc('X' + off, stream);
  389. return vfprintf_x64(num, off, stream) + 2;
  390. }
  391. if (num <= 15) {
  392. fputc(X_to_c(num) + off, stream);
  393. return 1;
  394. }
  395. int ret = vfprintf_x64(num >> 4, off, stream);
  396. fputc(X_to_c(num & 0xf) + off, stream);
  397. return ret + 1;
  398. }
  399. int vfprintf(FILE* stream, const char* fmt, va_list args)
  400. {
  401. int n = 0;
  402. for (char c = 0; (c = *fmt) != 0x00; ++fmt) {
  403. if (c == '%') {
  404. switch (*(++fmt)) {
  405. // int
  406. case 'd':
  407. n += vfprintf_d32(va_arg(args, int), stream);
  408. break;
  409. case 'x':
  410. n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
  411. break;
  412. case 'X':
  413. n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
  414. break;
  415. // long decimal
  416. case 'l':
  417. switch (*(++fmt)) {
  418. // long long aka int64
  419. case 'l':
  420. switch (*(++fmt)) {
  421. case 'd':
  422. n += vfprintf_d64(va_arg(args, long long), stream);
  423. break;
  424. case 'x':
  425. n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
  426. break;
  427. case 'X':
  428. n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
  429. break;
  430. }
  431. break;
  432. // long int aka int32
  433. case 'd':
  434. n += vfprintf_d32(va_arg(args, int), stream);
  435. break;
  436. case 'x':
  437. n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
  438. break;
  439. case 'X':
  440. n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
  441. break;
  442. }
  443. break;
  444. // c string
  445. case 's':
  446. n += fprintf(stream, va_arg(args, const char*));
  447. break;
  448. // int8 char
  449. case 'c':
  450. ++n;
  451. fputc(va_arg(args, int), stream);
  452. break;
  453. // pointer
  454. case 'p':
  455. #ifdef __32bit_system
  456. n += vfprintf_x32(va_arg(args, size_t), 'a' - 'A' + 1, stream);
  457. #else
  458. n += vfprintf_x64(va_arg(args, size_t), 'a' - 'A' + 1, stream);
  459. #endif
  460. break;
  461. default:
  462. ++n;
  463. fputc(*(fmt - 1), stream);
  464. break;
  465. }
  466. } else {
  467. ++n;
  468. fputc(c, stream);
  469. }
  470. }
  471. return n;
  472. }
  473. int fprintf(FILE* stream, const char* fmt, ...)
  474. {
  475. va_list args;
  476. va_start(args, fmt);
  477. int ret = vfprintf(stream, fmt, args);
  478. va_end(args);
  479. return ret;
  480. }
  481. int vprintf(const char* fmt, va_list args)
  482. {
  483. return vfprintf(stdout, fmt, args);
  484. }
  485. int printf(const char* fmt, ...)
  486. {
  487. va_list args;
  488. va_start(args, fmt);
  489. int ret = vprintf(fmt, args);
  490. va_end(args);
  491. return ret;
  492. }
  493. int putchar(int c)
  494. {
  495. fputc(c, stdout);
  496. return c;
  497. }
  498. FILE* fopen(const char* path, const char* mode)
  499. {
  500. uint32_t flags = 0, file_flags = 0;
  501. if (strcmp(mode, "r") == 0)
  502. flags = O_RDONLY, file_flags = FILE_READ;
  503. if (strcmp(mode, "r+") == 0)
  504. flags = O_RDWR, file_flags = FILE_READ | FILE_WRITE;
  505. if (strcmp(mode, "w") == 0)
  506. flags = O_WRONLY | O_CREAT | O_TRUNC, file_flags = FILE_WRITE;
  507. if (strcmp(mode, "w+") == 0)
  508. flags = O_RDWR | O_CREAT | O_TRUNC, file_flags = FILE_READ | FILE_WRITE;
  509. assert(flags);
  510. int fd = open(path, flags, 0644);
  511. if (fd < 0)
  512. goto open_fail;
  513. FILE* file = malloc(sizeof(FILE));
  514. if (!file)
  515. goto file_malloc_fail;
  516. file->fd = fd;
  517. file->flags = file_flags;
  518. if (file_flags & FILE_READ) {
  519. file->rbuf = malloc(BUFSIZ);
  520. if (!file->rbuf)
  521. goto rbuf_malloc_fail;
  522. file->rbsz = BUFSIZ;
  523. }
  524. if (file_flags & FILE_WRITE) {
  525. file->wbuf = malloc(BUFSIZ);
  526. if (!file->wbuf)
  527. goto wbuf_malloc_fail;
  528. file->wbsz = BUFSIZ;
  529. }
  530. return file;
  531. wbuf_malloc_fail:
  532. free(file->rbuf);
  533. rbuf_malloc_fail:
  534. free(file);
  535. file_malloc_fail:
  536. close(fd);
  537. open_fail:
  538. return NULL;
  539. }
  540. int fflush(FILE* stream)
  541. {
  542. if (__feof_or_error(stream))
  543. return EOF;
  544. if (stream->wbuf && stream->wpos) {
  545. int ret = write(stream->fd, stream->wbuf, stream->wpos);
  546. if (ret < 0) {
  547. stream->flags |= FILE_ERROR;
  548. return EOF;
  549. }
  550. if (ret == 0) {
  551. stream->flags |= FILE_EOF;
  552. return EOF;
  553. }
  554. stream->wpos = 0;
  555. }
  556. // TODO: call flush()
  557. return 0;
  558. }
  559. int fclose(FILE* stream)
  560. {
  561. if (fflush(stream) == EOF)
  562. return EOF;
  563. free(stream->rbuf);
  564. free(stream->wbuf);
  565. stream->rbsz = 0;
  566. stream->wbsz = 0;
  567. if (close(stream->fd) < 0)
  568. return EOF;
  569. NDERASE(NDPTR(stream));
  570. return 0;
  571. }
  572. int fputc_unlocked(int c, FILE* stream)
  573. {
  574. return putc_unlocked(c, stream);
  575. }
  576. int fputs_unlocked(const char* s, FILE* stream)
  577. {
  578. // 1 is for the trailing '\n'
  579. int len = 1;
  580. for (const char* p = s; *p; ++p, ++len)
  581. fputc_unlocked(*p, stream);
  582. fputc_unlocked('\n', stream);
  583. return len;
  584. }
  585. int fputc(int c, FILE* stream)
  586. {
  587. // TODO: lock the stream
  588. return putc_unlocked(c, stream);
  589. }
  590. int fputs(const char* s, FILE* stream)
  591. {
  592. // TODO: lock the stream
  593. return fputs_unlocked(s, stream);
  594. }
  595. static inline int __fillbuf(FILE* stream)
  596. {
  597. if ((stream->rcnt = read(stream->fd, stream->rbuf, stream->rbsz)) >= 2147483648U) {
  598. stream->rcnt = 0;
  599. stream->flags |= FILE_ERROR;
  600. return EOF;
  601. }
  602. if (stream->rcnt == 0) {
  603. stream->flags |= FILE_EOF;
  604. return EOF;
  605. }
  606. stream->rpos = 0;
  607. return 0;
  608. }
  609. int getc_unlocked(FILE* stream)
  610. {
  611. if (__feof_or_error(stream))
  612. return EOF;
  613. if (stream->rbuf) {
  614. if (stream->rpos == stream->rcnt) {
  615. if (__fillbuf(stream) < 0)
  616. return EOF;
  617. }
  618. return stream->rbuf[stream->rpos++];
  619. } else {
  620. int c;
  621. int ret = read(stream->fd, &c, 1);
  622. if (ret < 0) {
  623. stream->flags |= FILE_ERROR;
  624. return EOF;
  625. }
  626. if (ret == 0) {
  627. stream->flags |= FILE_EOF;
  628. return EOF;
  629. }
  630. return c;
  631. }
  632. }
  633. int putc_unlocked(int c, FILE* stream)
  634. {
  635. if (__feof_or_error(stream))
  636. return EOF;
  637. if (stream->wbuf) {
  638. stream->wbuf[stream->wpos++] = c;
  639. if (stream->wpos == stream->wbsz || c == '\n')
  640. if (fflush(stream) == EOF)
  641. return EOF;
  642. } else {
  643. if (write(stream->fd, &c, 1) < 0) {
  644. stream->flags |= FILE_ERROR;
  645. return EOF;
  646. }
  647. }
  648. return c;
  649. }
  650. int getchar(void)
  651. {
  652. return fgetc(stdin);
  653. }
  654. int fgetc(FILE* stream)
  655. {
  656. return getc_unlocked(stream);
  657. }
  658. int ferror(FILE* stream)
  659. {
  660. // TODO: lock the stream
  661. return ferror_unlocked(stream);
  662. }
  663. int ferror_unlocked(FILE* stream)
  664. {
  665. return stream->flags & FILE_ERROR;
  666. }
  667. int feof(FILE* stream)
  668. {
  669. return stream->flags & FILE_EOF;
  670. }
  671. void clearerr(FILE* stream)
  672. {
  673. stream->flags &= ~FILE_ERROR;
  674. }
  675. int vasprintf(char** strp, const char* fmt, va_list args)
  676. {
  677. // TODO: this is WAY TOO SLOWWWWWWWWW
  678. int sz = 8, n;
  679. char* buf = NULL;
  680. do {
  681. buf = realloc(buf, sz *= 2);
  682. if (!buf)
  683. return -1;
  684. n = vsnprintf(buf, sz, fmt, args);
  685. if (sz > n)
  686. break;
  687. } while (1);
  688. *strp = buf;
  689. return n;
  690. }
  691. int asprintf(char** strp, const char* fmt, ...)
  692. {
  693. va_list lst;
  694. va_start(lst, fmt);
  695. int ret = vasprintf(strp, fmt, lst);
  696. va_end(lst);
  697. return ret;
  698. }