printf.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /**
  2. * File: printf.c
  3. *
  4. * Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Kustaa Nyholm or SpareTimeLabs nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stddef.h>
  30. #include "atomic.h"
  31. #include "printf.h"
  32. #include "syscalls.h"
  33. /**
  34. * Configuration
  35. */
  36. /* Enable long int support */
  37. #define PRINTF_LONG_SUPPORT
  38. /* Enable long long int support (implies long int support) */
  39. #define PRINTF_LONG_LONG_SUPPORT
  40. /* Enable %z (size_t) support */
  41. #define PRINTF_SIZE_T_SUPPORT
  42. /**
  43. * Configuration adjustments
  44. */
  45. #if defined(PRINTF_LONG_LONG_SUPPORT)
  46. #define PRINTF_LONG_SUPPORT
  47. #endif
  48. /* __SIZEOF_<type>__ defined at least by gcc */
  49. #if defined(__SIZEOF_POINTER__)
  50. #define SIZEOF_POINTER __SIZEOF_POINTER__
  51. #endif
  52. #if defined(__SIZEOF_LONG_LONG__)
  53. #define SIZEOF_LONG_LONG __SIZEOF_LONG_LONG__
  54. #endif
  55. #if defined(__SIZEOF_LONG__)
  56. #define SIZEOF_LONG __SIZEOF_LONG__
  57. #endif
  58. #if defined(__SIZEOF_INT__)
  59. #define SIZEOF_INT __SIZEOF_INT__
  60. #endif
  61. #if defined(__GNUC__)
  62. #define _TFP_GCC_NO_INLINE_ __attribute__((noinline))
  63. #else
  64. #define _TFP_GCC_NO_INLINE_
  65. #endif
  66. #if defined(PRINTF_LONG_SUPPORT)
  67. #define BF_MAX 20 /* long = 64b on some architectures */
  68. #else
  69. #define BF_MAX 10 /* int = 32b on some architectures */
  70. #endif
  71. #define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
  72. /* Clear unused warnings for actually unused variables */
  73. #define UNUSED(x) (void)(x)
  74. /**
  75. * Implementation
  76. */
  77. struct param
  78. {
  79. char lz : 1; /* Leading zeros */
  80. char alt : 1; /* alternate form */
  81. char uc : 1; /* Upper case (for base16 only) */
  82. char align_left : 1; /* 0 == align right (default), 1 == align left */
  83. int width; /* field width */
  84. int prec; /* precision */
  85. char sign; /* The sign to display (if any) */
  86. unsigned int base; /* number base (e.g.: 8, 10, 16) */
  87. char *bf; /* Buffer to output */
  88. size_t bf_len; /* Buffer length */
  89. };
  90. static corelock_t lock = CORELOCK_INIT;
  91. #if defined(PRINTF_LONG_LONG_SUPPORT)
  92. static void _TFP_GCC_NO_INLINE_ ulli2a(unsigned long long int num, struct param *p)
  93. {
  94. unsigned long long int d = 1;
  95. char *bf = p->bf;
  96. if((p->prec == 0) && (num == 0))
  97. return;
  98. while(num / d >= p->base)
  99. {
  100. d *= p->base;
  101. }
  102. while(d != 0)
  103. {
  104. int dgt = num / d;
  105. num %= d;
  106. d /= p->base;
  107. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  108. }
  109. p->bf_len = bf - p->bf;
  110. }
  111. static void lli2a(long long int num, struct param *p)
  112. {
  113. if(num < 0)
  114. {
  115. num = -num;
  116. p->sign = '-';
  117. }
  118. ulli2a(num, p);
  119. }
  120. #endif
  121. #if defined(PRINTF_LONG_SUPPORT)
  122. static void uli2a(unsigned long int num, struct param *p)
  123. {
  124. unsigned long int d = 1;
  125. char *bf = p->bf;
  126. if((p->prec == 0) && (num == 0))
  127. return;
  128. while(num / d >= p->base)
  129. {
  130. d *= p->base;
  131. }
  132. while(d != 0)
  133. {
  134. int dgt = num / d;
  135. num %= d;
  136. d /= p->base;
  137. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  138. }
  139. p->bf_len = bf - p->bf;
  140. }
  141. static void li2a(long num, struct param *p)
  142. {
  143. if(num < 0)
  144. {
  145. num = -num;
  146. p->sign = '-';
  147. }
  148. uli2a(num, p);
  149. }
  150. #endif
  151. static void ui2a(unsigned int num, struct param *p)
  152. {
  153. unsigned int d = 1;
  154. char *bf = p->bf;
  155. if((p->prec == 0) && (num == 0))
  156. return;
  157. while(num / d >= p->base)
  158. {
  159. d *= p->base;
  160. }
  161. while(d != 0)
  162. {
  163. int dgt = num / d;
  164. num %= d;
  165. d /= p->base;
  166. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  167. }
  168. p->bf_len = bf - p->bf;
  169. }
  170. static void i2a(int num, struct param *p)
  171. {
  172. if(num < 0)
  173. {
  174. num = -num;
  175. p->sign = '-';
  176. }
  177. ui2a(num, p);
  178. }
  179. static int a2d(char ch)
  180. {
  181. if(IS_DIGIT(ch))
  182. return ch - '0';
  183. else if(ch >= 'a' && ch <= 'f')
  184. return ch - 'a' + 10;
  185. else if(ch >= 'A' && ch <= 'F')
  186. return ch - 'A' + 10;
  187. else
  188. return -1;
  189. }
  190. static char a2u(char ch, const char **src, int base, unsigned int *nump)
  191. {
  192. const char *p = *src;
  193. unsigned int num = 0;
  194. int digit;
  195. while((digit = a2d(ch)) >= 0)
  196. {
  197. if(digit > base)
  198. break;
  199. num = num * base + digit;
  200. ch = *p++;
  201. }
  202. *src = p;
  203. *nump = num;
  204. return ch;
  205. }
  206. static void putchw(void *putp, putcf putf, struct param *p)
  207. {
  208. char ch;
  209. int width = p->width;
  210. int prec = p->prec;
  211. char *bf = p->bf;
  212. size_t bf_len = p->bf_len;
  213. /* Number of filling characters */
  214. width -= bf_len;
  215. prec -= bf_len;
  216. if(p->sign)
  217. width--;
  218. if(p->alt && p->base == 16)
  219. width -= 2;
  220. else if(p->alt && p->base == 8)
  221. width--;
  222. if(prec > 0)
  223. width -= prec;
  224. /* Fill with space to align to the right, before alternate or sign */
  225. if(!p->lz && !p->align_left)
  226. {
  227. while(width-- > 0)
  228. putf(putp, ' ');
  229. }
  230. /* print sign */
  231. if(p->sign)
  232. putf(putp, p->sign);
  233. /* Alternate */
  234. if(p->alt && p->base == 16)
  235. {
  236. putf(putp, '0');
  237. putf(putp, (p->uc ? 'X' : 'x'));
  238. } else if(p->alt && p->base == 8)
  239. {
  240. putf(putp, '0');
  241. }
  242. /* Fill with zeros, after alternate or sign */
  243. while(prec-- > 0)
  244. putf(putp, '0');
  245. if(p->lz)
  246. {
  247. while(width-- > 0)
  248. putf(putp, '0');
  249. }
  250. /* Put actual buffer */
  251. while((bf_len-- > 0) && (ch = *bf++))
  252. putf(putp, ch);
  253. /* Fill with space to align to the left, after string */
  254. if(!p->lz && p->align_left)
  255. {
  256. while(width-- > 0)
  257. putf(putp, ' ');
  258. }
  259. }
  260. void tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
  261. {
  262. struct param p;
  263. char bf[BF_MAX];
  264. char ch;
  265. while((ch = *(fmt++)))
  266. {
  267. if(ch != '%')
  268. {
  269. putf(putp, ch);
  270. } else
  271. {
  272. #if defined(PRINTF_LONG_SUPPORT)
  273. char lng = 0; /* 1 for long, 2 for long long */
  274. #endif
  275. /* Init parameter struct */
  276. p.lz = 0;
  277. p.alt = 0;
  278. p.uc = 0;
  279. p.align_left = 0;
  280. p.width = 0;
  281. p.prec = -1;
  282. p.sign = 0;
  283. p.bf = bf;
  284. p.bf_len = 0;
  285. /* Flags */
  286. while((ch = *(fmt++)))
  287. {
  288. switch(ch)
  289. {
  290. case '-':
  291. p.align_left = 1;
  292. continue;
  293. case '0':
  294. p.lz = 1;
  295. continue;
  296. case '#':
  297. p.alt = 1;
  298. continue;
  299. default:
  300. break;
  301. }
  302. break;
  303. }
  304. if(p.align_left)
  305. p.lz = 0;
  306. /* Width */
  307. if(ch == '*')
  308. {
  309. ch = *(fmt++);
  310. p.width = va_arg(va, int);
  311. if(p.width < 0)
  312. {
  313. p.align_left = 1;
  314. p.width = -p.width;
  315. }
  316. } else if(IS_DIGIT(ch))
  317. {
  318. unsigned int width;
  319. ch = a2u(ch, &fmt, 10, &(width));
  320. p.width = width;
  321. }
  322. /* Precision */
  323. if(ch == '.')
  324. {
  325. ch = *(fmt++);
  326. if(ch == '*')
  327. {
  328. int prec;
  329. ch = *(fmt++);
  330. prec = va_arg(va, int);
  331. if(prec < 0)
  332. /* act as if precision was
  333. * omitted */
  334. p.prec = -1;
  335. else
  336. p.prec = prec;
  337. } else if(IS_DIGIT(ch))
  338. {
  339. unsigned int prec;
  340. ch = a2u(ch, &fmt, 10, &(prec));
  341. p.prec = prec;
  342. } else
  343. {
  344. p.prec = 0;
  345. }
  346. }
  347. if(p.prec >= 0)
  348. /* precision causes zero pad to be ignored */
  349. p.lz = 0;
  350. #if defined(PRINTF_SIZE_T_SUPPORT)
  351. #if defined(PRINTF_LONG_SUPPORT)
  352. if(ch == 'z')
  353. {
  354. ch = *(fmt++);
  355. if(sizeof(size_t) == sizeof(unsigned long int))
  356. lng = 1;
  357. #if defined(PRINTF_LONG_LONG_SUPPORT)
  358. else if(sizeof(size_t) == sizeof(unsigned long long int))
  359. lng = 2;
  360. #endif
  361. } else
  362. #endif
  363. #endif
  364. #if defined(PRINTF_LONG_SUPPORT)
  365. if(ch == 'l')
  366. {
  367. ch = *(fmt++);
  368. lng = 1;
  369. #if defined(PRINTF_LONG_LONG_SUPPORT)
  370. if(ch == 'l')
  371. {
  372. ch = *(fmt++);
  373. lng = 2;
  374. }
  375. #endif
  376. }
  377. #endif
  378. switch(ch)
  379. {
  380. case 0:
  381. goto abort;
  382. case 'u':
  383. p.base = 10;
  384. if(p.prec < 0)
  385. p.prec = 1;
  386. #if defined(PRINTF_LONG_SUPPORT)
  387. #if defined(PRINTF_LONG_LONG_SUPPORT)
  388. if(2 == lng)
  389. ulli2a(va_arg(va, unsigned long long int), &p);
  390. else
  391. #endif
  392. if(1 == lng)
  393. uli2a(va_arg(va, unsigned long int), &p);
  394. else
  395. #endif
  396. ui2a(va_arg(va, unsigned int), &p);
  397. putchw(putp, putf, &p);
  398. break;
  399. case 'd': /* No break */
  400. case 'i':
  401. p.base = 10;
  402. if(p.prec < 0)
  403. p.prec = 1;
  404. #if defined(PRINTF_LONG_SUPPORT)
  405. #if defined(PRINTF_LONG_LONG_SUPPORT)
  406. if(2 == lng)
  407. lli2a(va_arg(va, long long int), &p);
  408. else
  409. #endif
  410. if(1 == lng)
  411. li2a(va_arg(va, long int), &p);
  412. else
  413. #endif
  414. i2a(va_arg(va, int), &p);
  415. putchw(putp, putf, &p);
  416. break;
  417. #if defined(SIZEOF_POINTER)
  418. case 'p':
  419. p.alt = 1;
  420. #if defined(SIZEOF_INT) && SIZEOF_POINTER <= SIZEOF_INT
  421. lng = 0;
  422. #elif defined(SIZEOF_LONG) && SIZEOF_POINTER <= SIZEOF_LONG
  423. lng = 1;
  424. #elif defined(SIZEOF_LONG_LONG) && SIZEOF_POINTER <= SIZEOF_LONG_LONG
  425. lng = 2;
  426. #endif
  427. #endif
  428. /* No break */
  429. case 'x': /* No break */
  430. case 'X':
  431. p.base = 16;
  432. p.uc = (ch == 'X') ? 1 : 0;
  433. if(p.prec < 0)
  434. p.prec = 1;
  435. #if defined(PRINTF_LONG_SUPPORT)
  436. #if defined(PRINTF_LONG_LONG_SUPPORT)
  437. if(2 == lng)
  438. ulli2a(va_arg(va, unsigned long long int), &p);
  439. else
  440. #endif
  441. if(1 == lng)
  442. uli2a(va_arg(va, unsigned long int), &p);
  443. else
  444. #endif
  445. ui2a(va_arg(va, unsigned int), &p);
  446. putchw(putp, putf, &p);
  447. break;
  448. case 'o':
  449. p.base = 8;
  450. if(p.prec < 0)
  451. p.prec = 1;
  452. ui2a(va_arg(va, unsigned int), &p);
  453. putchw(putp, putf, &p);
  454. break;
  455. case 'c':
  456. putf(putp, (char)(va_arg(va, int)));
  457. break;
  458. case 's':
  459. {
  460. unsigned int prec = p.prec;
  461. char *b;
  462. p.bf = va_arg(va, char *);
  463. b = p.bf;
  464. while((prec-- != 0) && *b++)
  465. {
  466. p.bf_len++;
  467. }
  468. p.prec = -1;
  469. putchw(putp, putf, &p);
  470. }
  471. break;
  472. case '%':
  473. putf(putp, ch);
  474. break;
  475. default:
  476. break;
  477. }
  478. }
  479. }
  480. abort:;
  481. }
  482. #if defined(TINYPRINTF_DEFINE_TFP_PRINTF)
  483. static putcf stdout_putf;
  484. static void *stdout_putp;
  485. void init_printf(void *putp, putcf putf)
  486. {
  487. stdout_putf = putf;
  488. stdout_putp = putp;
  489. }
  490. void tfp_printf(char *fmt, ...)
  491. {
  492. va_list va;
  493. va_start(va, fmt);
  494. tfp_format(stdout_putp, stdout_putf, fmt, va);
  495. va_end(va);
  496. }
  497. #endif
  498. #if defined(TINYPRINTF_DEFINE_TFP_SPRINTF)
  499. struct _vsnprintf_putcf_data
  500. {
  501. size_t dest_capacity;
  502. char *dest;
  503. size_t num_chars;
  504. };
  505. static void _vsnprintf_putcf(void *p, char c)
  506. {
  507. struct _vsnprintf_putcf_data *data = (struct _vsnprintf_putcf_data *)p;
  508. if(data->num_chars < data->dest_capacity)
  509. data->dest[data->num_chars] = c;
  510. data->num_chars++;
  511. }
  512. int tfp_vsnprintf(char *str, size_t size, const char *format, va_list ap)
  513. {
  514. struct _vsnprintf_putcf_data data;
  515. if(size < 1)
  516. return 0;
  517. data.dest = str;
  518. data.dest_capacity = size - 1;
  519. data.num_chars = 0;
  520. tfp_format(&data, _vsnprintf_putcf, format, ap);
  521. if(data.num_chars < data.dest_capacity)
  522. data.dest[data.num_chars] = '\0';
  523. else
  524. data.dest[data.dest_capacity] = '\0';
  525. return data.num_chars;
  526. }
  527. int tfp_snprintf(char *str, size_t size, const char *format, ...)
  528. {
  529. va_list ap;
  530. int retval;
  531. va_start(ap, format);
  532. retval = tfp_vsnprintf(str, size, format, ap);
  533. va_end(ap);
  534. return retval;
  535. }
  536. struct _vsprintf_putcf_data
  537. {
  538. char *dest;
  539. size_t num_chars;
  540. };
  541. static void _vsprintf_putcf(void *p, char c)
  542. {
  543. struct _vsprintf_putcf_data *data = (struct _vsprintf_putcf_data *)p;
  544. data->dest[data->num_chars++] = c;
  545. }
  546. int tfp_vsprintf(char *str, const char *format, va_list ap)
  547. {
  548. struct _vsprintf_putcf_data data;
  549. data.dest = str;
  550. data.num_chars = 0;
  551. tfp_format(&data, _vsprintf_putcf, format, ap);
  552. data.dest[data.num_chars] = '\0';
  553. return data.num_chars;
  554. }
  555. int tfp_sprintf(char *str, const char *format, ...)
  556. {
  557. va_list ap;
  558. int retval;
  559. va_start(ap, format);
  560. retval = tfp_vsprintf(str, format, ap);
  561. va_end(ap);
  562. return retval;
  563. }
  564. #endif
  565. static void uart_putf(void *unused, char c)
  566. {
  567. UNUSED(unused);
  568. if(sys_putchar)
  569. sys_putchar(c);
  570. }
  571. int printk(const char *format, ...)
  572. {
  573. va_list ap;
  574. va_start(ap, format);
  575. /* Begin protected code */
  576. corelock_lock(&lock);
  577. tfp_format(stdout_putp, uart_putf, format, ap);
  578. /* End protected code */
  579. corelock_unlock(&lock);
  580. va_end(ap);
  581. return 0;
  582. }