tiny-printf.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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 printf(const char *fmt, ...)
  36. {
  37. va_list va;
  38. char ch;
  39. char *p;
  40. unsigned int num;
  41. char buf[12];
  42. unsigned int div;
  43. va_start(va, fmt);
  44. while ((ch = *(fmt++))) {
  45. if (ch != '%') {
  46. putc(ch);
  47. } else {
  48. char lz = 0;
  49. char w = 0;
  50. ch = *(fmt++);
  51. if (ch == '0') {
  52. ch = *(fmt++);
  53. lz = 1;
  54. }
  55. if (ch >= '0' && ch <= '9') {
  56. w = 0;
  57. while (ch >= '0' && ch <= '9') {
  58. w = (w * 10) + ch - '0';
  59. ch = *fmt++;
  60. }
  61. }
  62. bf = buf;
  63. p = bf;
  64. zs = 0;
  65. switch (ch) {
  66. case 0:
  67. goto abort;
  68. case 'u':
  69. case 'd':
  70. num = va_arg(va, unsigned int);
  71. if (ch == 'd' && (int)num < 0) {
  72. num = -(int)num;
  73. out('-');
  74. }
  75. for (div = 1000000000; div; div /= 10)
  76. div_out(&num, div);
  77. break;
  78. case 'x':
  79. num = va_arg(va, unsigned int);
  80. for (div = 0x10000000; div; div /= 0x10)
  81. div_out(&num, div);
  82. break;
  83. case 'c':
  84. out((char)(va_arg(va, int)));
  85. break;
  86. case 's':
  87. p = va_arg(va, char*);
  88. break;
  89. case '%':
  90. out('%');
  91. default:
  92. break;
  93. }
  94. *bf = 0;
  95. bf = p;
  96. while (*bf++ && w > 0)
  97. w--;
  98. while (w-- > 0)
  99. putc(lz ? '0' : ' ');
  100. while ((ch = *p++))
  101. putc(ch);
  102. }
  103. }
  104. abort:
  105. va_end(va);
  106. return 0;
  107. }