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
14
15static int xmon_write(const void *ptr, int nb)
16{
17	return udbg_write(ptr, nb);
18}
19
20static int xmon_readchar(void)
21{
22	if (udbg_getc)
23		return udbg_getc();
24	return -1;
25}
26
27int xmon_putchar(int c)
28{
29	char ch = c;
30
31	if (c == '\n')
32		xmon_putchar('\r');
33	return xmon_write(&ch, 1) == 1? c: -1;
34}
35
36static char line[256];
37static char *lineptr;
38static int lineleft;
39
40static int xmon_getchar(void)
41{
42	int c;
43
44	if (lineleft == 0) {
45		lineptr = line;
46		for (;;) {
47			c = xmon_readchar();
48			if (c == -1 || c == 4)
49				break;
50			if (c == '\r' || c == '\n') {
51				*lineptr++ = '\n';
52				xmon_putchar('\n');
53				break;
54			}
55			switch (c) {
56			case 0177:
57			case '\b':
58				if (lineptr > line) {
59					xmon_putchar('\b');
60					xmon_putchar(' ');
61					xmon_putchar('\b');
62					--lineptr;
63				}
64				break;
65			case 'U' & 0x1F:
66				while (lineptr > line) {
67					xmon_putchar('\b');
68					xmon_putchar(' ');
69					xmon_putchar('\b');
70					--lineptr;
71				}
72				break;
73			default:
74				if (lineptr >= &line[sizeof(line) - 1])
75					xmon_putchar('\a');
76				else {
77					xmon_putchar(c);
78					*lineptr++ = c;
79				}
80			}
81		}
82		lineleft = lineptr - line;
83		lineptr = line;
84	}
85	if (lineleft == 0)
86		return -1;
87	--lineleft;
88	return *lineptr++;
89}
90
91char *xmon_gets(char *str, int nb)
92{
93	char *p;
94	int c;
95
96	for (p = str; p < str + nb - 1; ) {
97		c = xmon_getchar();
98		if (c == -1) {
99			if (p == str)
100				return NULL;
101			break;
102		}
103		*p++ = c;
104		if (c == '\n')
105			break;
106	}
107	*p = 0;
108	return str;
109}
110
111void xmon_printf(const char *format, ...)
112{
113	va_list args;
114	static char xmon_outbuf[1024];
115	int rc, n;
116
117	va_start(args, format);
118	n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
119	va_end(args);
120
121	rc = xmon_write(xmon_outbuf, n);
122
123	if (n && rc == 0) {
124		/* No udbg hooks, fallback to printk() - dangerous */
125		printk("%s", xmon_outbuf);
126	}
127}
128
129void xmon_puts(const char *str)
130{
131	xmon_write(str, strlen(str));
132}
133