123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /*
- * Copyright (C) 1996-2005 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
- #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 */
- printk("%s", xmon_outbuf);
- }
- }
- void xmon_puts(const char *str)
- {
- xmon_write(str, strlen(str));
- }
|