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 buf[12];
  16. static unsigned int num;
  17. static char uc;
  18. static char zs;
  19. static void out(char c)
  20. {
  21. *bf++ = c;
  22. }
  23. static void out_dgt(char dgt)
  24. {
  25. out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
  26. zs = 1;
  27. }
  28. static void div_out(unsigned int div)
  29. {
  30. unsigned char dgt = 0;
  31. num &= 0xffff; /* just for testing the code with 32 bit ints */
  32. while (num >= div) {
  33. num -= div;
  34. dgt++;
  35. }
  36. if (zs || dgt > 0)
  37. out_dgt(dgt);
  38. }
  39. int printf(const char *fmt, ...)
  40. {
  41. va_list va;
  42. char ch;
  43. char *p;
  44. va_start(va, fmt);
  45. while ((ch = *(fmt++))) {
  46. if (ch != '%') {
  47. putc(ch);
  48. } else {
  49. char lz = 0;
  50. char w = 0;
  51. ch = *(fmt++);
  52. if (ch == '0') {
  53. ch = *(fmt++);
  54. lz = 1;
  55. }
  56. if (ch >= '0' && ch <= '9') {
  57. w = 0;
  58. while (ch >= '0' && ch <= '9') {
  59. w = (((w << 2) + w) << 1) + ch - '0';
  60. ch = *fmt++;
  61. }
  62. }
  63. bf = buf;
  64. p = bf;
  65. zs = 0;
  66. switch (ch) {
  67. case 0:
  68. goto abort;
  69. case 'u':
  70. case 'd':
  71. num = va_arg(va, unsigned int);
  72. if (ch == 'd' && (int)num < 0) {
  73. num = -(int)num;
  74. out('-');
  75. }
  76. div_out(10000);
  77. div_out(1000);
  78. div_out(100);
  79. div_out(10);
  80. out_dgt(num);
  81. break;
  82. case 'x':
  83. case 'X':
  84. uc = ch == 'X';
  85. num = va_arg(va, unsigned int);
  86. div_out(0x1000);
  87. div_out(0x100);
  88. div_out(0x10);
  89. out_dgt(num);
  90. break;
  91. case 'c':
  92. out((char)(va_arg(va, int)));
  93. break;
  94. case 's':
  95. p = va_arg(va, char*);
  96. break;
  97. case '%':
  98. out('%');
  99. default:
  100. break;
  101. }
  102. *bf = 0;
  103. bf = p;
  104. while (*bf++ && w > 0)
  105. w--;
  106. while (w-- > 0)
  107. putc(lz ? '0' : ' ');
  108. while ((ch = *p++))
  109. putc(ch);
  110. }
  111. }
  112. abort:
  113. va_end(va);
  114. return 0;
  115. }