stdio.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "stdio.h"
  2. #include "stdarg.h"
  3. #include "types.h"
  4. #include <Kernel/Syscall.h>
  5. #define ALWAYS_INLINE __attribute__ ((always_inline))
  6. static const char h[] = { '0','1','2','3','4','5','6','7', '8','9','a','b','c','d','e','f' };
  7. template<typename PutChFunc>
  8. ALWAYS_INLINE int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields)
  9. {
  10. int ret = 0;
  11. byte shr_count = fields * 4;
  12. while (shr_count) {
  13. shr_count -= 4;
  14. putch(bufptr, h[(number >> shr_count) & 0x0F]);
  15. ++ret;
  16. }
  17. return ret;
  18. }
  19. template<typename PutChFunc>
  20. ALWAYS_INLINE int printNumber(PutChFunc putch, char*& bufptr, dword number)
  21. {
  22. dword divisor = 1000000000;
  23. char ch;
  24. char padding = 1;
  25. int ret = 0;
  26. for (;;) {
  27. ch = '0' + (number / divisor);
  28. number %= divisor;
  29. if (ch != '0')
  30. padding = 0;
  31. if (!padding || divisor == 1) {
  32. putch(bufptr, ch);
  33. ++ret;
  34. }
  35. if (divisor == 1)
  36. break;
  37. divisor /= 10;
  38. }
  39. return ret;
  40. }
  41. template<typename PutChFunc>
  42. ALWAYS_INLINE int printSignedNumber(PutChFunc putch, char*& bufptr, int number)
  43. {
  44. if (number < 0) {
  45. putch(bufptr, '-');
  46. return printNumber(putch, bufptr, 0 - number) + 1;
  47. }
  48. return printNumber(putch, bufptr, number);
  49. }
  50. static void sys_putch(char*, char ch)
  51. {
  52. Syscall::invoke(Syscall::PutCharacter, ch);
  53. }
  54. template<typename PutChFunc>
  55. int printfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap)
  56. {
  57. const char *p;
  58. int ret = 0;
  59. char* bufptr = buffer;
  60. for (p = fmt; *p; ++p) {
  61. if (*p == '%' && *(p + 1)) {
  62. ++p;
  63. switch( *p )
  64. {
  65. case 's':
  66. {
  67. const char* sp = va_arg(ap, const char*);
  68. //ASSERT(sp != nullptr);
  69. if (!sp) {
  70. putch(bufptr, '(');
  71. putch(bufptr, 'n');
  72. putch(bufptr, 'u');
  73. putch(bufptr, 'l');
  74. putch(bufptr, 'l');
  75. putch(bufptr, ')');
  76. ret += 6;
  77. } else {
  78. for (; *sp; ++sp) {
  79. putch(bufptr, *sp);
  80. ++ret;
  81. }
  82. }
  83. }
  84. break;
  85. case 'd':
  86. ret += printSignedNumber(putch, bufptr, va_arg(ap, int));
  87. break;
  88. case 'u':
  89. ret += printNumber(putch, bufptr, va_arg(ap, dword));
  90. break;
  91. case 'x':
  92. ret += printHex(putch, bufptr, va_arg(ap, dword), 8);
  93. break;
  94. case 'w':
  95. ret += printHex(putch, bufptr, va_arg(ap, int), 4);
  96. break;
  97. case 'b':
  98. ret += printHex(putch, bufptr, va_arg(ap, int), 2);
  99. break;
  100. case 'c':
  101. putch(bufptr, (char)va_arg(ap, int));
  102. ++ret;
  103. break;
  104. case 'p':
  105. putch(bufptr, '0');
  106. putch(bufptr, 'x');
  107. ret += 2;
  108. ret += printHex(putch, bufptr, va_arg(ap, dword), 8);
  109. break;
  110. }
  111. }
  112. else {
  113. putch(bufptr, *p);
  114. ++ret;
  115. }
  116. }
  117. return ret;
  118. }
  119. extern "C" {
  120. int putchar(int ch)
  121. {
  122. Syscall::invoke(Syscall::PutCharacter, ch);
  123. return (byte)ch;
  124. }
  125. int printf(const char* fmt, ...)
  126. {
  127. va_list ap;
  128. va_start(ap, fmt);
  129. int ret = printfInternal(sys_putch, nullptr, fmt, ap);
  130. va_end(ap);
  131. return ret;
  132. }
  133. static void buffer_putch(char*& bufptr, char ch)
  134. {
  135. *bufptr++ = ch;
  136. }
  137. int sprintf(char* buffer, const char* fmt, ...)
  138. {
  139. va_list ap;
  140. va_start(ap, fmt);
  141. int ret = printfInternal(buffer_putch, buffer, fmt, ap);
  142. buffer[ret] = '\0';
  143. va_end(ap);
  144. return ret;
  145. }
  146. }