tiny-printf.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Tiny printf version for SPL
  3. *
  4. * Copied from:
  5. * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
  6. *
  7. * Copyright (C) 2004,2008 Kustaa Nyholm
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1+
  10. */
  11. #include <common.h>
  12. #include <stdarg.h>
  13. #include <serial.h>
  14. static char *bf;
  15. static char zs;
  16. static void out(char c)
  17. {
  18. *bf++ = c;
  19. }
  20. static void out_dgt(char dgt)
  21. {
  22. out(dgt + (dgt < 10 ? '0' : 'a' - 10));
  23. zs = 1;
  24. }
  25. static void div_out(unsigned int *num, unsigned int div)
  26. {
  27. unsigned char dgt = 0;
  28. while (*num >= div) {
  29. *num -= div;
  30. dgt++;
  31. }
  32. if (zs || dgt > 0)
  33. out_dgt(dgt);
  34. }
  35. int vprintf(const char *fmt, va_list va)
  36. {
  37. char ch;
  38. char *p;
  39. unsigned int num;
  40. char buf[12];
  41. unsigned int div;
  42. while ((ch = *(fmt++))) {
  43. if (ch != '%') {
  44. putc(ch);
  45. } else {
  46. char lz = 0;
  47. char w = 0;
  48. ch = *(fmt++);
  49. if (ch == '0') {
  50. ch = *(fmt++);
  51. lz = 1;
  52. }
  53. if (ch >= '0' && ch <= '9') {
  54. w = 0;
  55. while (ch >= '0' && ch <= '9') {
  56. w = (w * 10) + ch - '0';
  57. ch = *fmt++;
  58. }
  59. }
  60. bf = buf;
  61. p = bf;
  62. zs = 0;
  63. switch (ch) {
  64. case 0:
  65. goto abort;
  66. case 'u':
  67. case 'd':
  68. num = va_arg(va, unsigned int);
  69. if (ch == 'd' && (int)num < 0) {
  70. num = -(int)num;
  71. out('-');
  72. }
  73. if (!num) {
  74. out_dgt(0);
  75. } else {
  76. for (div = 1000000000; div; div /= 10)
  77. div_out(&num, div);
  78. }
  79. break;
  80. case 'x':
  81. num = va_arg(va, unsigned int);
  82. if (!num) {
  83. out_dgt(0);
  84. } else {
  85. for (div = 0x10000000; div; div /= 0x10)
  86. div_out(&num, div);
  87. }
  88. break;
  89. case 'c':
  90. out((char)(va_arg(va, int)));
  91. break;
  92. case 's':
  93. p = va_arg(va, char*);
  94. break;
  95. case '%':
  96. out('%');
  97. default:
  98. break;
  99. }
  100. *bf = 0;
  101. bf = p;
  102. while (*bf++ && w > 0)
  103. w--;
  104. while (w-- > 0)
  105. putc(lz ? '0' : ' ');
  106. if (p) {
  107. while ((ch = *p++))
  108. putc(ch);
  109. }
  110. }
  111. }
  112. abort:
  113. return 0;
  114. }
  115. int printf(const char *fmt, ...)
  116. {
  117. va_list va;
  118. int ret;
  119. va_start(va, fmt);
  120. ret = vprintf(fmt, va);
  121. va_end(va);
  122. return ret;
  123. }