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