xref: /openbmc/linux/arch/powerpc/xmon/nonstdio.c (revision 455f9726)
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 
15 static int xmon_write(const void *ptr, int nb)
16 {
17 	return udbg_write(ptr, nb);
18 }
19 
20 static int xmon_readchar(void)
21 {
22 	if (udbg_getc)
23 		return udbg_getc();
24 	return -1;
25 }
26 
27 int 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 
36 static char line[256];
37 static char *lineptr;
38 static int lineleft;
39 
40 static 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 
91 char *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 
111 void 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 
129 void xmon_puts(const char *str)
130 {
131 	xmon_write(str, strlen(str));
132 }
133