0001
0002
0003
0004
0005 #include <linux/string.h>
0006 #include <asm/udbg.h>
0007 #include <asm/time.h>
0008 #include "nonstdio.h"
0009
0010 static bool paginating, paginate_skipping;
0011 static unsigned long paginate_lpp;
0012 static unsigned long paginate_pos;
0013
0014 void xmon_start_pagination(void)
0015 {
0016 paginating = true;
0017 paginate_skipping = false;
0018 paginate_pos = 0;
0019 }
0020
0021 void xmon_end_pagination(void)
0022 {
0023 paginating = false;
0024 }
0025
0026 void xmon_set_pagination_lpp(unsigned long lpp)
0027 {
0028 paginate_lpp = lpp;
0029 }
0030
0031 static int xmon_readchar(void)
0032 {
0033 if (udbg_getc)
0034 return udbg_getc();
0035 return -1;
0036 }
0037
0038 static int xmon_write(const char *ptr, int nb)
0039 {
0040 int rv = 0;
0041 const char *p = ptr, *q;
0042 const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
0043
0044 if (nb <= 0)
0045 return rv;
0046
0047 if (paginating && paginate_skipping)
0048 return nb;
0049
0050 if (paginate_lpp) {
0051 while (paginating && (q = strchr(p, '\n'))) {
0052 rv += udbg_write(p, q - p + 1);
0053 p = q + 1;
0054 paginate_pos++;
0055
0056 if (paginate_pos >= paginate_lpp) {
0057 udbg_write(msg, strlen(msg));
0058
0059 switch (xmon_readchar()) {
0060 case 'a':
0061 paginating = false;
0062 break;
0063 case 'q':
0064 paginate_skipping = true;
0065 break;
0066 default:
0067
0068 break;
0069 }
0070
0071 paginate_pos = 0;
0072 udbg_write("\r\n", 2);
0073
0074 if (paginate_skipping)
0075 return nb;
0076 }
0077 }
0078 }
0079
0080 return rv + udbg_write(p, nb - (p - ptr));
0081 }
0082
0083 int xmon_putchar(int c)
0084 {
0085 char ch = c;
0086
0087 if (c == '\n')
0088 xmon_putchar('\r');
0089 return xmon_write(&ch, 1) == 1? c: -1;
0090 }
0091
0092 static char line[256];
0093 static char *lineptr;
0094 static int lineleft;
0095
0096 static int xmon_getchar(void)
0097 {
0098 int c;
0099
0100 if (lineleft == 0) {
0101 lineptr = line;
0102 for (;;) {
0103 c = xmon_readchar();
0104 if (c == -1 || c == 4)
0105 break;
0106 if (c == '\r' || c == '\n') {
0107 *lineptr++ = '\n';
0108 xmon_putchar('\n');
0109 break;
0110 }
0111 switch (c) {
0112 case 0177:
0113 case '\b':
0114 if (lineptr > line) {
0115 xmon_putchar('\b');
0116 xmon_putchar(' ');
0117 xmon_putchar('\b');
0118 --lineptr;
0119 }
0120 break;
0121 case 'U' & 0x1F:
0122 while (lineptr > line) {
0123 xmon_putchar('\b');
0124 xmon_putchar(' ');
0125 xmon_putchar('\b');
0126 --lineptr;
0127 }
0128 break;
0129 default:
0130 if (lineptr >= &line[sizeof(line) - 1])
0131 xmon_putchar('\a');
0132 else {
0133 xmon_putchar(c);
0134 *lineptr++ = c;
0135 }
0136 }
0137 }
0138 lineleft = lineptr - line;
0139 lineptr = line;
0140 }
0141 if (lineleft == 0)
0142 return -1;
0143 --lineleft;
0144 return *lineptr++;
0145 }
0146
0147 char *xmon_gets(char *str, int nb)
0148 {
0149 char *p;
0150 int c;
0151
0152 for (p = str; p < str + nb - 1; ) {
0153 c = xmon_getchar();
0154 if (c == -1) {
0155 if (p == str)
0156 return NULL;
0157 break;
0158 }
0159 *p++ = c;
0160 if (c == '\n')
0161 break;
0162 }
0163 *p = 0;
0164 return str;
0165 }
0166
0167 void xmon_printf(const char *format, ...)
0168 {
0169 va_list args;
0170 static char xmon_outbuf[1024];
0171 int rc, n;
0172
0173 va_start(args, format);
0174 n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
0175 va_end(args);
0176
0177 rc = xmon_write(xmon_outbuf, n);
0178
0179 if (n && rc == 0) {
0180
0181 pr_cont("%s", xmon_outbuf);
0182 }
0183 }
0184
0185 void xmon_puts(const char *str)
0186 {
0187 xmon_write(str, strlen(str));
0188 }