mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
3.1 KiB
188 lines
3.1 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* Copyright (C) 1996-2005 Paul Mackerras. |
|
*/ |
|
#include <linux/string.h> |
|
#include <asm/udbg.h> |
|
#include <asm/time.h> |
|
#include "nonstdio.h" |
|
|
|
static bool paginating, paginate_skipping; |
|
static unsigned long paginate_lpp; /* Lines Per Page */ |
|
static unsigned long paginate_pos; |
|
|
|
void xmon_start_pagination(void) |
|
{ |
|
paginating = true; |
|
paginate_skipping = false; |
|
paginate_pos = 0; |
|
} |
|
|
|
void xmon_end_pagination(void) |
|
{ |
|
paginating = false; |
|
} |
|
|
|
void xmon_set_pagination_lpp(unsigned long lpp) |
|
{ |
|
paginate_lpp = lpp; |
|
} |
|
|
|
static int xmon_readchar(void) |
|
{ |
|
if (udbg_getc) |
|
return udbg_getc(); |
|
return -1; |
|
} |
|
|
|
static int xmon_write(const char *ptr, int nb) |
|
{ |
|
int rv = 0; |
|
const char *p = ptr, *q; |
|
const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]"; |
|
|
|
if (nb <= 0) |
|
return rv; |
|
|
|
if (paginating && paginate_skipping) |
|
return nb; |
|
|
|
if (paginate_lpp) { |
|
while (paginating && (q = strchr(p, '\n'))) { |
|
rv += udbg_write(p, q - p + 1); |
|
p = q + 1; |
|
paginate_pos++; |
|
|
|
if (paginate_pos >= paginate_lpp) { |
|
udbg_write(msg, strlen(msg)); |
|
|
|
switch (xmon_readchar()) { |
|
case 'a': |
|
paginating = false; |
|
break; |
|
case 'q': |
|
paginate_skipping = true; |
|
break; |
|
default: |
|
/* nothing */ |
|
break; |
|
} |
|
|
|
paginate_pos = 0; |
|
udbg_write("\r\n", 2); |
|
|
|
if (paginate_skipping) |
|
return nb; |
|
} |
|
} |
|
} |
|
|
|
return rv + udbg_write(p, nb - (p - ptr)); |
|
} |
|
|
|
int xmon_putchar(int c) |
|
{ |
|
char ch = c; |
|
|
|
if (c == '\n') |
|
xmon_putchar('\r'); |
|
return xmon_write(&ch, 1) == 1? c: -1; |
|
} |
|
|
|
static char line[256]; |
|
static char *lineptr; |
|
static int lineleft; |
|
|
|
static int xmon_getchar(void) |
|
{ |
|
int c; |
|
|
|
if (lineleft == 0) { |
|
lineptr = line; |
|
for (;;) { |
|
c = xmon_readchar(); |
|
if (c == -1 || c == 4) |
|
break; |
|
if (c == '\r' || c == '\n') { |
|
*lineptr++ = '\n'; |
|
xmon_putchar('\n'); |
|
break; |
|
} |
|
switch (c) { |
|
case 0177: |
|
case '\b': |
|
if (lineptr > line) { |
|
xmon_putchar('\b'); |
|
xmon_putchar(' '); |
|
xmon_putchar('\b'); |
|
--lineptr; |
|
} |
|
break; |
|
case 'U' & 0x1F: |
|
while (lineptr > line) { |
|
xmon_putchar('\b'); |
|
xmon_putchar(' '); |
|
xmon_putchar('\b'); |
|
--lineptr; |
|
} |
|
break; |
|
default: |
|
if (lineptr >= &line[sizeof(line) - 1]) |
|
xmon_putchar('\a'); |
|
else { |
|
xmon_putchar(c); |
|
*lineptr++ = c; |
|
} |
|
} |
|
} |
|
lineleft = lineptr - line; |
|
lineptr = line; |
|
} |
|
if (lineleft == 0) |
|
return -1; |
|
--lineleft; |
|
return *lineptr++; |
|
} |
|
|
|
char *xmon_gets(char *str, int nb) |
|
{ |
|
char *p; |
|
int c; |
|
|
|
for (p = str; p < str + nb - 1; ) { |
|
c = xmon_getchar(); |
|
if (c == -1) { |
|
if (p == str) |
|
return NULL; |
|
break; |
|
} |
|
*p++ = c; |
|
if (c == '\n') |
|
break; |
|
} |
|
*p = 0; |
|
return str; |
|
} |
|
|
|
void xmon_printf(const char *format, ...) |
|
{ |
|
va_list args; |
|
static char xmon_outbuf[1024]; |
|
int rc, n; |
|
|
|
va_start(args, format); |
|
n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args); |
|
va_end(args); |
|
|
|
rc = xmon_write(xmon_outbuf, n); |
|
|
|
if (n && rc == 0) { |
|
/* No udbg hooks, fallback to printk() - dangerous */ |
|
pr_cont("%s", xmon_outbuf); |
|
} |
|
} |
|
|
|
void xmon_puts(const char *str) |
|
{ |
|
xmon_write(str, strlen(str)); |
|
}
|
|
|