stdio.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * minimal stdio function definitions for NOLIBC
  4. * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
  5. */
  6. #ifndef _NOLIBC_STDIO_H
  7. #define _NOLIBC_STDIO_H
  8. #include "std.h"
  9. #include "arch.h"
  10. #include "errno.h"
  11. #include "types.h"
  12. #include "sys.h"
  13. #include "stdarg.h"
  14. #include "stdlib.h"
  15. #include "string.h"
  16. #ifndef EOF
  17. #define EOF (-1)
  18. #endif
  19. /* Buffering mode used by setvbuf. */
  20. #define _IOFBF 0 /* Fully buffered. */
  21. #define _IOLBF 1 /* Line buffered. */
  22. #define _IONBF 2 /* No buffering. */
  23. /* just define FILE as a non-empty type. The value of the pointer gives
  24. * the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE
  25. * are immediately identified as abnormal entries (i.e. possible copies
  26. * of valid pointers to something else).
  27. */
  28. typedef struct FILE {
  29. char dummy[1];
  30. } FILE;
  31. static __attribute__((unused)) FILE* const stdin = (FILE*)(intptr_t)~STDIN_FILENO;
  32. static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO;
  33. static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO;
  34. /* provides a FILE* equivalent of fd. The mode is ignored. */
  35. static __attribute__((unused))
  36. FILE *fdopen(int fd, const char *mode __attribute__((unused)))
  37. {
  38. if (fd < 0) {
  39. SET_ERRNO(EBADF);
  40. return NULL;
  41. }
  42. return (FILE*)(intptr_t)~fd;
  43. }
  44. /* provides the fd of stream. */
  45. static __attribute__((unused))
  46. int fileno(FILE *stream)
  47. {
  48. intptr_t i = (intptr_t)stream;
  49. if (i >= 0) {
  50. SET_ERRNO(EBADF);
  51. return -1;
  52. }
  53. return ~i;
  54. }
  55. /* flush a stream. */
  56. static __attribute__((unused))
  57. int fflush(FILE *stream)
  58. {
  59. intptr_t i = (intptr_t)stream;
  60. /* NULL is valid here. */
  61. if (i > 0) {
  62. SET_ERRNO(EBADF);
  63. return -1;
  64. }
  65. /* Don't do anything, nolibc does not support buffering. */
  66. return 0;
  67. }
  68. /* flush a stream. */
  69. static __attribute__((unused))
  70. int fclose(FILE *stream)
  71. {
  72. intptr_t i = (intptr_t)stream;
  73. if (i >= 0) {
  74. SET_ERRNO(EBADF);
  75. return -1;
  76. }
  77. if (close(~i))
  78. return EOF;
  79. return 0;
  80. }
  81. /* getc(), fgetc(), getchar() */
  82. #define getc(stream) fgetc(stream)
  83. static __attribute__((unused))
  84. int fgetc(FILE* stream)
  85. {
  86. unsigned char ch;
  87. if (read(fileno(stream), &ch, 1) <= 0)
  88. return EOF;
  89. return ch;
  90. }
  91. static __attribute__((unused))
  92. int getchar(void)
  93. {
  94. return fgetc(stdin);
  95. }
  96. /* putc(), fputc(), putchar() */
  97. #define putc(c, stream) fputc(c, stream)
  98. static __attribute__((unused))
  99. int fputc(int c, FILE* stream)
  100. {
  101. unsigned char ch = c;
  102. if (write(fileno(stream), &ch, 1) <= 0)
  103. return EOF;
  104. return ch;
  105. }
  106. static __attribute__((unused))
  107. int putchar(int c)
  108. {
  109. return fputc(c, stdout);
  110. }
  111. /* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
  112. /* internal fwrite()-like function which only takes a size and returns 0 on
  113. * success or EOF on error. It automatically retries on short writes.
  114. */
  115. static __attribute__((unused))
  116. int _fwrite(const void *buf, size_t size, FILE *stream)
  117. {
  118. ssize_t ret;
  119. int fd = fileno(stream);
  120. while (size) {
  121. ret = write(fd, buf, size);
  122. if (ret <= 0)
  123. return EOF;
  124. size -= ret;
  125. buf += ret;
  126. }
  127. return 0;
  128. }
  129. static __attribute__((unused))
  130. size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
  131. {
  132. size_t written;
  133. for (written = 0; written < nmemb; written++) {
  134. if (_fwrite(s, size, stream) != 0)
  135. break;
  136. s += size;
  137. }
  138. return written;
  139. }
  140. static __attribute__((unused))
  141. int fputs(const char *s, FILE *stream)
  142. {
  143. return _fwrite(s, strlen(s), stream);
  144. }
  145. static __attribute__((unused))
  146. int puts(const char *s)
  147. {
  148. if (fputs(s, stdout) == EOF)
  149. return EOF;
  150. return putchar('\n');
  151. }
  152. /* fgets() */
  153. static __attribute__((unused))
  154. char *fgets(char *s, int size, FILE *stream)
  155. {
  156. int ofs;
  157. int c;
  158. for (ofs = 0; ofs + 1 < size;) {
  159. c = fgetc(stream);
  160. if (c == EOF)
  161. break;
  162. s[ofs++] = c;
  163. if (c == '\n')
  164. break;
  165. }
  166. if (ofs < size)
  167. s[ofs] = 0;
  168. return ofs ? s : NULL;
  169. }
  170. /* minimal vfprintf(). It supports the following formats:
  171. * - %[l*]{d,u,c,x,p}
  172. * - %s
  173. * - unknown modifiers are ignored.
  174. */
  175. static __attribute__((unused, format(printf, 2, 0)))
  176. int vfprintf(FILE *stream, const char *fmt, va_list args)
  177. {
  178. char escape, lpref, c;
  179. unsigned long long v;
  180. unsigned int written;
  181. size_t len, ofs;
  182. char tmpbuf[21];
  183. const char *outstr;
  184. written = ofs = escape = lpref = 0;
  185. while (1) {
  186. c = fmt[ofs++];
  187. if (escape) {
  188. /* we're in an escape sequence, ofs == 1 */
  189. escape = 0;
  190. if (c == 'c' || c == 'd' || c == 'u' || c == 'x' || c == 'p') {
  191. char *out = tmpbuf;
  192. if (c == 'p')
  193. v = va_arg(args, unsigned long);
  194. else if (lpref) {
  195. if (lpref > 1)
  196. v = va_arg(args, unsigned long long);
  197. else
  198. v = va_arg(args, unsigned long);
  199. } else
  200. v = va_arg(args, unsigned int);
  201. if (c == 'd') {
  202. /* sign-extend the value */
  203. if (lpref == 0)
  204. v = (long long)(int)v;
  205. else if (lpref == 1)
  206. v = (long long)(long)v;
  207. }
  208. switch (c) {
  209. case 'c':
  210. out[0] = v;
  211. out[1] = 0;
  212. break;
  213. case 'd':
  214. i64toa_r(v, out);
  215. break;
  216. case 'u':
  217. u64toa_r(v, out);
  218. break;
  219. case 'p':
  220. *(out++) = '0';
  221. *(out++) = 'x';
  222. /* fall through */
  223. default: /* 'x' and 'p' above */
  224. u64toh_r(v, out);
  225. break;
  226. }
  227. outstr = tmpbuf;
  228. }
  229. else if (c == 's') {
  230. outstr = va_arg(args, char *);
  231. if (!outstr)
  232. outstr="(null)";
  233. }
  234. else if (c == '%') {
  235. /* queue it verbatim */
  236. continue;
  237. }
  238. else {
  239. /* modifiers or final 0 */
  240. if (c == 'l') {
  241. /* long format prefix, maintain the escape */
  242. lpref++;
  243. }
  244. escape = 1;
  245. goto do_escape;
  246. }
  247. len = strlen(outstr);
  248. goto flush_str;
  249. }
  250. /* not an escape sequence */
  251. if (c == 0 || c == '%') {
  252. /* flush pending data on escape or end */
  253. escape = 1;
  254. lpref = 0;
  255. outstr = fmt;
  256. len = ofs - 1;
  257. flush_str:
  258. if (_fwrite(outstr, len, stream) != 0)
  259. break;
  260. written += len;
  261. do_escape:
  262. if (c == 0)
  263. break;
  264. fmt += ofs;
  265. ofs = 0;
  266. continue;
  267. }
  268. /* literal char, just queue it */
  269. }
  270. return written;
  271. }
  272. static __attribute__((unused, format(printf, 1, 0)))
  273. int vprintf(const char *fmt, va_list args)
  274. {
  275. return vfprintf(stdout, fmt, args);
  276. }
  277. static __attribute__((unused, format(printf, 2, 3)))
  278. int fprintf(FILE *stream, const char *fmt, ...)
  279. {
  280. va_list args;
  281. int ret;
  282. va_start(args, fmt);
  283. ret = vfprintf(stream, fmt, args);
  284. va_end(args);
  285. return ret;
  286. }
  287. static __attribute__((unused, format(printf, 1, 2)))
  288. int printf(const char *fmt, ...)
  289. {
  290. va_list args;
  291. int ret;
  292. va_start(args, fmt);
  293. ret = vfprintf(stdout, fmt, args);
  294. va_end(args);
  295. return ret;
  296. }
  297. static __attribute__((unused))
  298. void perror(const char *msg)
  299. {
  300. fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
  301. }
  302. static __attribute__((unused))
  303. int setvbuf(FILE *stream __attribute__((unused)),
  304. char *buf __attribute__((unused)),
  305. int mode,
  306. size_t size __attribute__((unused)))
  307. {
  308. /*
  309. * nolibc does not support buffering so this is a nop. Just check mode
  310. * is valid as required by the spec.
  311. */
  312. switch (mode) {
  313. case _IOFBF:
  314. case _IOLBF:
  315. case _IONBF:
  316. break;
  317. default:
  318. return EOF;
  319. }
  320. return 0;
  321. }
  322. static __attribute__((unused))
  323. const char *strerror(int errno)
  324. {
  325. static char buf[18] = "errno=";
  326. i64toa_r(errno, &buf[6]);
  327. return buf;
  328. }
  329. /* make sure to include all global symbols */
  330. #include "nolibc.h"
  331. #endif /* _NOLIBC_STDIO_H */