nonstdio.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 1996-2005 Paul Mackerras.
  4. */
  5. #include <linux/string.h>
  6. #include <asm/udbg.h>
  7. #include <asm/time.h>
  8. #include "nonstdio.h"
  9. static bool paginating, paginate_skipping;
  10. static unsigned long paginate_lpp; /* Lines Per Page */
  11. static unsigned long paginate_pos;
  12. void xmon_start_pagination(void)
  13. {
  14. paginating = true;
  15. paginate_skipping = false;
  16. paginate_pos = 0;
  17. }
  18. void xmon_end_pagination(void)
  19. {
  20. paginating = false;
  21. }
  22. void xmon_set_pagination_lpp(unsigned long lpp)
  23. {
  24. paginate_lpp = lpp;
  25. }
  26. static int xmon_readchar(void)
  27. {
  28. if (udbg_getc)
  29. return udbg_getc();
  30. return -1;
  31. }
  32. static int xmon_write(const char *ptr, int nb)
  33. {
  34. int rv = 0;
  35. const char *p = ptr, *q;
  36. const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
  37. if (nb <= 0)
  38. return rv;
  39. if (paginating && paginate_skipping)
  40. return nb;
  41. if (paginate_lpp) {
  42. while (paginating && (q = strchr(p, '\n'))) {
  43. rv += udbg_write(p, q - p + 1);
  44. p = q + 1;
  45. paginate_pos++;
  46. if (paginate_pos >= paginate_lpp) {
  47. udbg_write(msg, strlen(msg));
  48. switch (xmon_readchar()) {
  49. case 'a':
  50. paginating = false;
  51. break;
  52. case 'q':
  53. paginate_skipping = true;
  54. break;
  55. default:
  56. /* nothing */
  57. break;
  58. }
  59. paginate_pos = 0;
  60. udbg_write("\r\n", 2);
  61. if (paginate_skipping)
  62. return nb;
  63. }
  64. }
  65. }
  66. return rv + udbg_write(p, nb - (p - ptr));
  67. }
  68. int xmon_putchar(int c)
  69. {
  70. char ch = c;
  71. if (c == '\n')
  72. xmon_putchar('\r');
  73. return xmon_write(&ch, 1) == 1? c: -1;
  74. }
  75. static char line[256];
  76. static char *lineptr;
  77. static int lineleft;
  78. static int xmon_getchar(void)
  79. {
  80. int c;
  81. if (lineleft == 0) {
  82. lineptr = line;
  83. for (;;) {
  84. c = xmon_readchar();
  85. if (c == -1 || c == 4)
  86. break;
  87. if (c == '\r' || c == '\n') {
  88. *lineptr++ = '\n';
  89. xmon_putchar('\n');
  90. break;
  91. }
  92. switch (c) {
  93. case 0177:
  94. case '\b':
  95. if (lineptr > line) {
  96. xmon_putchar('\b');
  97. xmon_putchar(' ');
  98. xmon_putchar('\b');
  99. --lineptr;
  100. }
  101. break;
  102. case 'U' & 0x1F:
  103. while (lineptr > line) {
  104. xmon_putchar('\b');
  105. xmon_putchar(' ');
  106. xmon_putchar('\b');
  107. --lineptr;
  108. }
  109. break;
  110. default:
  111. if (lineptr >= &line[sizeof(line) - 1])
  112. xmon_putchar('\a');
  113. else {
  114. xmon_putchar(c);
  115. *lineptr++ = c;
  116. }
  117. }
  118. }
  119. lineleft = lineptr - line;
  120. lineptr = line;
  121. }
  122. if (lineleft == 0)
  123. return -1;
  124. --lineleft;
  125. return *lineptr++;
  126. }
  127. char *xmon_gets(char *str, int nb)
  128. {
  129. char *p;
  130. int c;
  131. for (p = str; p < str + nb - 1; ) {
  132. c = xmon_getchar();
  133. if (c == -1) {
  134. if (p == str)
  135. return NULL;
  136. break;
  137. }
  138. *p++ = c;
  139. if (c == '\n')
  140. break;
  141. }
  142. *p = 0;
  143. return str;
  144. }
  145. void xmon_printf(const char *format, ...)
  146. {
  147. va_list args;
  148. static char xmon_outbuf[1024];
  149. int rc, n;
  150. va_start(args, format);
  151. n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
  152. va_end(args);
  153. rc = xmon_write(xmon_outbuf, n);
  154. if (n && rc == 0) {
  155. /* No udbg hooks, fallback to printk() - dangerous */
  156. pr_cont("%s", xmon_outbuf);
  157. }
  158. }
  159. void xmon_puts(const char *str)
  160. {
  161. xmon_write(str, strlen(str));
  162. }