2005-11-08 14:55:08 +03:00
/*
* 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>
2012-10-09 08:20:32 +04:00
# include <asm/udbg.h>
2005-11-08 14:55:08 +03:00
# include <asm/time.h>
# include "nonstdio.h"
2015-10-08 03:50:23 +03:00
static bool paginating , paginate_skipping ;
static unsigned long paginate_lpp ; /* Lines Per Page */
static unsigned long paginate_pos ;
2012-10-09 08:20:32 +04:00
2015-10-08 03:50:23 +03:00
void xmon_start_pagination ( void )
2012-10-09 08:20:32 +04:00
{
2015-10-08 03:50:23 +03:00
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 ;
2012-10-09 08:20:32 +04:00
}
static int xmon_readchar ( void )
{
if ( udbg_getc )
return udbg_getc ( ) ;
return - 1 ;
}
2015-10-08 03:50:23 +03:00
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 ) ) ;
}
2005-11-08 14:55:08 +03:00
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 ;
2012-10-09 08:20:31 +04:00
static int xmon_getchar ( void )
2005-11-08 14:55:08 +03:00
{
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 ] ;
2012-10-09 08:20:47 +04:00
int rc , n ;
2005-11-08 14:55:08 +03:00
va_start ( args , format ) ;
n = vsnprintf ( xmon_outbuf , sizeof ( xmon_outbuf ) , format , args ) ;
va_end ( args ) ;
2012-10-09 08:20:47 +04:00
rc = xmon_write ( xmon_outbuf , n ) ;
if ( n & & rc = = 0 ) {
/* No udbg hooks, fallback to printk() - dangerous */
2014-06-10 21:54:06 +04:00
printk ( " %s " , xmon_outbuf ) ;
2012-10-09 08:20:47 +04:00
}
2005-11-08 14:55:08 +03:00
}
2007-07-18 13:26:40 +04:00
void xmon_puts ( const char * str )
{
xmon_write ( str , strlen ( str ) ) ;
}