tiny-printf.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. for (div = 1000000000; div; div /= 10)
  74. div_out(&num, div);
  75. break;
  76. case 'x':
  77. num = va_arg(va, unsigned int);
  78. for (div = 0x10000000; div; div /= 0x10)
  79. div_out(&num, div);
  80. break;
  81. case 'c':
  82. out((char)(va_arg(va, int)));
  83. break;
  84. case 's':
  85. p = va_arg(va, char*);
  86. break;
  87. case '%':
  88. out('%');
  89. default:
  90. break;
  91. }
  92. *bf = 0;
  93. bf = p;
  94. while (*bf++ && w > 0)
  95. w--;
  96. while (w-- > 0)
  97. putc(lz ? '0' : ' ');
  98. while ((ch = *p++))
  99. putc(ch);
  100. }
  101. }
  102. abort:
  103. return 0;
  104. }
  105. int printf(const char *fmt, ...)
  106. {
  107. va_list va;
  108. int ret;
  109. va_start(va, fmt);
  110. ret = vprintf(fmt, va);
  111. va_end(va);
  112. return ret;
  113. }