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