dbg_printf.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* $NetBSD: printf.c,v 1.12 1997/06/26 19:11:48 drochner Exp $ */
  2. /*-
  3. * Copyright (c) 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by the University of
  17. * California, Berkeley and its contributors.
  18. * 4. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * @(#)printf.c 8.1 (Berkeley) 6/11/93
  35. */
  36. // This version uses almost no stack, and does not suffer from buffer
  37. // overflows. The downside is that it does not implement a wide range
  38. // of formatting characters.
  39. #include <c_stdlib.h>
  40. #include <c_types.h>
  41. #include <c_stdarg.h>
  42. #include "driver/uart.h"
  43. static void kprintn (void (*)(const char), uint32_t, int, int, char);
  44. static void kdoprnt (void (*)(const char), const char *, va_list);
  45. void
  46. dbg_printf(const char *fmt, ...)
  47. {
  48. va_list ap;
  49. va_start(ap, fmt);
  50. kdoprnt(uart0_putc, fmt, ap);
  51. va_end(ap);
  52. }
  53. void
  54. dbg_vprintf(const char *fmt, va_list ap)
  55. {
  56. kdoprnt(uart0_putc, fmt, ap);
  57. }
  58. void
  59. kdoprnt(void (*put)(const char), const char *fmt, va_list ap)
  60. {
  61. register char *p;
  62. register int ch, n;
  63. unsigned long ul;
  64. int lflag, set;
  65. char zwidth;
  66. char width;
  67. for (;;) {
  68. while ((ch = *fmt++) != '%') {
  69. if (ch == '\0')
  70. return;
  71. put(ch);
  72. }
  73. lflag = 0;
  74. width = 0;
  75. zwidth = ' ';
  76. reswitch: switch (ch = *fmt++) {
  77. case '\0':
  78. /* XXX print the last format character? */
  79. return;
  80. case 'l':
  81. lflag = 1;
  82. goto reswitch;
  83. case 'c':
  84. ch = va_arg(ap, int);
  85. put(ch & 0x7f);
  86. break;
  87. case 's':
  88. p = va_arg(ap, char *);
  89. if (p == 0) {
  90. p = "<null>";
  91. }
  92. while ((ch = *p++))
  93. put(ch);
  94. break;
  95. case 'd':
  96. ul = lflag ?
  97. va_arg(ap, long) : va_arg(ap, int);
  98. if ((long)ul < 0) {
  99. put('-');
  100. ul = -(long)ul;
  101. }
  102. kprintn(put, ul, 10, width, zwidth);
  103. break;
  104. case 'o':
  105. ul = lflag ?
  106. va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
  107. kprintn(put, ul, 8, width, zwidth);
  108. break;
  109. case 'u':
  110. ul = lflag ?
  111. va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
  112. kprintn(put, ul, 10, width, zwidth);
  113. break;
  114. case 'x':
  115. ul = lflag ?
  116. va_arg(ap, uint32_t) : va_arg(ap, uint32_t);
  117. kprintn(put, ul, 16, width, zwidth);
  118. break;
  119. default:
  120. if (ch >= '0' && ch <= '9') {
  121. if (ch == '0' && width == 0 && zwidth == ' ') {
  122. zwidth = '0';
  123. } else {
  124. width = width * 10 + ch - '0';
  125. }
  126. goto reswitch;
  127. }
  128. put('%');
  129. if (lflag)
  130. put('l');
  131. put(ch);
  132. }
  133. }
  134. va_end(ap);
  135. }
  136. static void
  137. kprintn(void (*put)(const char), uint32_t ul, int base, int width, char padchar)
  138. {
  139. /* hold a long in base 8 */
  140. char *p, buf[(sizeof(long) * 8 / 3) + 2];
  141. p = buf;
  142. do {
  143. *p++ = "0123456789abcdef"[ul % base];
  144. } while (ul /= base);
  145. while (p - buf < width--) {
  146. put(padchar);
  147. }
  148. do {
  149. put(*--p);
  150. } while (p > buf);
  151. }