Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/xmon/nonstdio.c
26444 views
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
10
static bool paginating, paginate_skipping;
11
static unsigned long paginate_lpp; /* Lines Per Page */
12
static unsigned long paginate_pos;
13
14
void xmon_start_pagination(void)
15
{
16
paginating = true;
17
paginate_skipping = false;
18
paginate_pos = 0;
19
}
20
21
void xmon_end_pagination(void)
22
{
23
paginating = false;
24
}
25
26
void xmon_set_pagination_lpp(unsigned long lpp)
27
{
28
paginate_lpp = lpp;
29
}
30
31
static int xmon_readchar(void)
32
{
33
if (udbg_getc)
34
return udbg_getc();
35
return -1;
36
}
37
38
static int xmon_write(const char *ptr, int nb)
39
{
40
int rv = 0;
41
const char *p = ptr, *q;
42
const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
43
44
if (nb <= 0)
45
return rv;
46
47
if (paginating && paginate_skipping)
48
return nb;
49
50
if (paginate_lpp) {
51
while (paginating && (q = strchr(p, '\n'))) {
52
rv += udbg_write(p, q - p + 1);
53
p = q + 1;
54
paginate_pos++;
55
56
if (paginate_pos >= paginate_lpp) {
57
udbg_write(msg, strlen(msg));
58
59
switch (xmon_readchar()) {
60
case 'a':
61
paginating = false;
62
break;
63
case 'q':
64
paginate_skipping = true;
65
break;
66
default:
67
/* nothing */
68
break;
69
}
70
71
paginate_pos = 0;
72
udbg_write("\r\n", 2);
73
74
if (paginate_skipping)
75
return nb;
76
}
77
}
78
}
79
80
return rv + udbg_write(p, nb - (p - ptr));
81
}
82
83
int xmon_putchar(int c)
84
{
85
char ch = c;
86
87
if (c == '\n')
88
xmon_putchar('\r');
89
return xmon_write(&ch, 1) == 1? c: -1;
90
}
91
92
static char line[256];
93
static char *lineptr;
94
static int lineleft;
95
96
static int xmon_getchar(void)
97
{
98
int c;
99
100
if (lineleft == 0) {
101
lineptr = line;
102
for (;;) {
103
c = xmon_readchar();
104
if (c == -1 || c == 4)
105
break;
106
if (c == '\r' || c == '\n') {
107
*lineptr++ = '\n';
108
xmon_putchar('\n');
109
break;
110
}
111
switch (c) {
112
case 0177:
113
case '\b':
114
if (lineptr > line) {
115
xmon_putchar('\b');
116
xmon_putchar(' ');
117
xmon_putchar('\b');
118
--lineptr;
119
}
120
break;
121
case 'U' & 0x1F:
122
while (lineptr > line) {
123
xmon_putchar('\b');
124
xmon_putchar(' ');
125
xmon_putchar('\b');
126
--lineptr;
127
}
128
break;
129
default:
130
if (lineptr >= &line[sizeof(line) - 1])
131
xmon_putchar('\a');
132
else {
133
xmon_putchar(c);
134
*lineptr++ = c;
135
}
136
}
137
}
138
lineleft = lineptr - line;
139
lineptr = line;
140
}
141
if (lineleft == 0)
142
return -1;
143
--lineleft;
144
return *lineptr++;
145
}
146
147
char *xmon_gets(char *str, int nb)
148
{
149
char *p;
150
int c;
151
152
for (p = str; p < str + nb - 1; ) {
153
c = xmon_getchar();
154
if (c == -1) {
155
if (p == str)
156
return NULL;
157
break;
158
}
159
*p++ = c;
160
if (c == '\n')
161
break;
162
}
163
*p = 0;
164
return str;
165
}
166
167
void xmon_printf(const char *format, ...)
168
{
169
va_list args;
170
static char xmon_outbuf[1024];
171
int rc, n;
172
173
va_start(args, format);
174
n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
175
va_end(args);
176
177
rc = xmon_write(xmon_outbuf, n);
178
179
if (n && rc == 0) {
180
/* No udbg hooks, fallback to printk() - dangerous */
181
pr_cont("%s", xmon_outbuf);
182
}
183
}
184
185
void xmon_puts(const char *str)
186
{
187
xmon_write(str, strlen(str));
188
}
189
190