Line data Source code
1 : /* $OpenBSD: db_input.c,v 1.16 2016/04/19 12:23:25 mpi Exp $ */
2 : /* $NetBSD: db_input.c,v 1.7 1996/02/05 01:57:02 christos Exp $ */
3 :
4 : /*
5 : * Mach Operating System
6 : * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7 : * All Rights Reserved.
8 : *
9 : * Permission to use, copy, modify and distribute this software and its
10 : * documentation is hereby granted, provided that both the copyright
11 : * notice and this permission notice appear in all copies of the
12 : * software, derivative works or modified versions, and any portions
13 : * thereof, and that both notices appear in supporting documentation.
14 : *
15 : * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 : * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 : * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 : *
19 : * Carnegie Mellon requests users of this software to return to
20 : *
21 : * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 : * School of Computer Science
23 : * Carnegie Mellon University
24 : * Pittsburgh PA 15213-3890
25 : *
26 : * any improvements or extensions that they make and grant Carnegie Mellon
27 : * the rights to redistribute these changes.
28 : *
29 : * Author: David B. Golub, Carnegie Mellon University
30 : * Date: 7/90
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/systm.h>
35 :
36 : #include <machine/db_machdep.h>
37 :
38 : #include <ddb/db_var.h>
39 : #include <ddb/db_output.h>
40 : #include <ddb/db_sym.h>
41 : #include <ddb/db_extern.h>
42 :
43 : #include <dev/cons.h>
44 :
45 : /*
46 : * Character input and editing.
47 : */
48 :
49 : void db_putstring(char *, int);
50 : void db_putnchars(int, int);
51 : void db_delete(int, int);
52 : void db_delete_line(void);
53 : int db_inputchar(int);
54 :
55 : /*
56 : * We don't track output position while editing input,
57 : * since input always ends with a new-line. We just
58 : * reset the line position at the end.
59 : */
60 : char * db_lbuf_start; /* start of input line buffer */
61 : char * db_lbuf_end; /* end of input line buffer */
62 : char * db_lc; /* current character */
63 : char * db_le; /* one past last character */
64 : #if DB_HISTORY_SIZE != 0
65 : char db_history[DB_HISTORY_SIZE]; /* start of history buffer */
66 : int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
67 : char * db_history_curr = db_history; /* start of current line */
68 : char * db_history_last = db_history; /* start of last line */
69 : char * db_history_prev = (char *) 0; /* start of previous line */
70 : #endif
71 :
72 :
73 : #define CTRL(c) ((c) & 0x1f)
74 : #define isspace(c) ((c) == ' ' || (c) == '\t')
75 : #define BLANK ' '
76 : #define BACKUP '\b'
77 :
78 : void
79 0 : db_putstring(char *s, int count)
80 : {
81 0 : while (--count >= 0)
82 0 : cnputc(*s++);
83 0 : }
84 :
85 : void
86 0 : db_putnchars(int c, int count)
87 : {
88 0 : while (--count >= 0)
89 0 : cnputc(c);
90 0 : }
91 :
92 : /*
93 : * Delete N characters, forward or backward
94 : */
95 : #define DEL_FWD 0
96 : #define DEL_BWD 1
97 : void
98 0 : db_delete(int n, int bwd)
99 : {
100 : char *p;
101 :
102 0 : if (bwd) {
103 0 : db_lc -= n;
104 0 : db_putnchars(BACKUP, n);
105 0 : }
106 0 : for (p = db_lc; p < db_le-n; p++) {
107 0 : *p = *(p+n);
108 0 : cnputc(*p);
109 : }
110 0 : db_putnchars(BLANK, n);
111 0 : db_putnchars(BACKUP, db_le - db_lc);
112 0 : db_le -= n;
113 0 : }
114 :
115 : void
116 0 : db_delete_line(void)
117 : {
118 0 : db_delete(db_le - db_lc, DEL_FWD);
119 0 : db_delete(db_lc - db_lbuf_start, DEL_BWD);
120 0 : db_le = db_lc = db_lbuf_start;
121 0 : }
122 :
123 : #if DB_HISTORY_SIZE != 0
124 : #define INC_DB_CURR() \
125 : do { \
126 : db_history_curr++; \
127 : if (db_history_curr > \
128 : db_history + db_history_size - 1) \
129 : db_history_curr = db_history; \
130 : } while (0)
131 : #define DEC_DB_CURR() \
132 : do { \
133 : db_history_curr--; \
134 : if (db_history_curr < db_history) \
135 : db_history_curr = db_history + \
136 : db_history_size - 1; \
137 : } while (0)
138 : #endif
139 :
140 : /* returns TRUE at end-of-line */
141 : int
142 0 : db_inputchar(int c)
143 : {
144 0 : switch (c) {
145 : case CTRL('b'):
146 : /* back up one character */
147 0 : if (db_lc > db_lbuf_start) {
148 0 : cnputc(BACKUP);
149 0 : db_lc--;
150 0 : }
151 : break;
152 : case CTRL('f'):
153 : /* forward one character */
154 0 : if (db_lc < db_le) {
155 0 : cnputc(*db_lc);
156 0 : db_lc++;
157 0 : }
158 : break;
159 : case CTRL('a'):
160 : /* beginning of line */
161 0 : while (db_lc > db_lbuf_start) {
162 0 : cnputc(BACKUP);
163 0 : db_lc--;
164 : }
165 : break;
166 : case CTRL('e'):
167 : /* end of line */
168 0 : while (db_lc < db_le) {
169 0 : cnputc(*db_lc);
170 0 : db_lc++;
171 : }
172 : break;
173 : case CTRL('w'):
174 : /* erase word back */
175 0 : while (db_lc > db_lbuf_start && db_lc[-1] != BLANK)
176 0 : db_delete(1, DEL_BWD);
177 : break;
178 : case CTRL('h'):
179 : case 0177:
180 : /* erase previous character */
181 0 : if (db_lc > db_lbuf_start)
182 0 : db_delete(1, DEL_BWD);
183 : break;
184 : case CTRL('d'):
185 : /* erase next character */
186 0 : if (db_lc < db_le)
187 0 : db_delete(1, DEL_FWD);
188 : break;
189 : case CTRL('k'):
190 : /* delete to end of line */
191 0 : if (db_lc < db_le)
192 0 : db_delete(db_le - db_lc, DEL_FWD);
193 : break;
194 : case CTRL('u'):
195 : /* delete line */
196 0 : db_delete_line();
197 0 : break;
198 : case CTRL('t'):
199 : /* twiddle last 2 characters */
200 0 : if (db_lc >= db_lbuf_start + 2) {
201 0 : c = db_lc[-2];
202 0 : db_lc[-2] = db_lc[-1];
203 0 : db_lc[-1] = c;
204 0 : cnputc(BACKUP);
205 0 : cnputc(BACKUP);
206 0 : cnputc(db_lc[-2]);
207 0 : cnputc(db_lc[-1]);
208 0 : }
209 : break;
210 : #if DB_HISTORY_SIZE != 0
211 : case CTRL('p'):
212 0 : DEC_DB_CURR();
213 0 : while (db_history_curr != db_history_last) {
214 0 : DEC_DB_CURR();
215 0 : if (*db_history_curr == '\0')
216 : break;
217 : }
218 0 : db_delete_line();
219 0 : if (db_history_curr == db_history_last) {
220 0 : INC_DB_CURR();
221 0 : db_le = db_lc = db_lbuf_start;
222 0 : } else {
223 : char *p;
224 0 : INC_DB_CURR();
225 0 : for (p = db_history_curr, db_le = db_lbuf_start;*p; ) {
226 0 : *db_le++ = *p++;
227 0 : if (p == db_history + db_history_size)
228 0 : p = db_history;
229 : }
230 0 : db_lc = db_le;
231 : }
232 0 : db_putstring(db_lbuf_start, db_le - db_lbuf_start);
233 0 : break;
234 : case CTRL('n'):
235 0 : while (db_history_curr != db_history_last) {
236 0 : if (*db_history_curr == '\0')
237 : break;
238 0 : INC_DB_CURR();
239 : }
240 0 : if (db_history_curr != db_history_last) {
241 0 : INC_DB_CURR();
242 0 : db_delete_line();
243 0 : if (db_history_curr != db_history_last) {
244 : char *p;
245 0 : for (p = db_history_curr,
246 0 : db_le = db_lbuf_start; *p;) {
247 0 : *db_le++ = *p++;
248 0 : if (p == db_history + db_history_size)
249 0 : p = db_history;
250 : }
251 0 : db_lc = db_le;
252 0 : }
253 0 : db_putstring(db_lbuf_start, db_le - db_lbuf_start);
254 0 : }
255 : break;
256 : #endif
257 : case CTRL('r'):
258 0 : db_putstring("^R\n", 3);
259 0 : if (db_le > db_lbuf_start) {
260 0 : db_putstring(db_lbuf_start, db_le - db_lbuf_start);
261 0 : db_putnchars(BACKUP, db_le - db_lc);
262 0 : }
263 : break;
264 : case '\n':
265 : case '\r':
266 : #if DB_HISTORY_SIZE != 0
267 : /*
268 : * Check whether current line is the same
269 : * as previous saved line. If it is, don`t
270 : * save it.
271 : */
272 0 : if (db_history_curr == db_history_prev) {
273 : char *pp, *pc;
274 :
275 : /*
276 : * Is it the same?
277 : */
278 0 : for (pp = db_history_prev, pc = db_lbuf_start;
279 0 : pc != db_le && *pp; ) {
280 0 : if (*pp != *pc)
281 : break;
282 0 : if (++pp == db_history + db_history_size)
283 : pp = db_history;
284 0 : pc++;
285 : }
286 0 : if (!*pp && pc == db_le) {
287 : /*
288 : * Repeated previous line. Don`t save.
289 : */
290 0 : db_history_curr = db_history_last;
291 0 : *db_le++ = c;
292 0 : return TRUE;
293 : }
294 0 : }
295 0 : if (db_le != db_lbuf_start) {
296 : char *p;
297 0 : db_history_prev = db_history_last;
298 0 : for (p = db_lbuf_start; p != db_le; p++) {
299 0 : *db_history_last++ = *p;
300 0 : if (db_history_last ==
301 0 : db_history + db_history_size)
302 0 : db_history_last = db_history;
303 : }
304 0 : *db_history_last++ = '\0';
305 0 : }
306 0 : db_history_curr = db_history_last;
307 : #endif
308 0 : *db_le++ = c;
309 0 : return TRUE;
310 : default:
311 0 : if (db_le == db_lbuf_end) {
312 0 : cnputc('\007');
313 0 : }
314 0 : else if (c >= ' ' && c <= '~') {
315 : char *p;
316 :
317 0 : for (p = db_le; p > db_lc; p--)
318 0 : *p = *(p-1);
319 0 : *db_lc++ = c;
320 0 : db_le++;
321 0 : cnputc(c);
322 0 : db_putstring(db_lc, db_le - db_lc);
323 0 : db_putnchars(BACKUP, db_le - db_lc);
324 0 : }
325 : break;
326 : }
327 0 : return FALSE;
328 0 : }
329 :
330 : int
331 0 : db_readline(char *lstart, int lsize)
332 : {
333 0 : db_force_whitespace(); /* synch output position */
334 :
335 0 : db_lbuf_start = lstart;
336 0 : db_lbuf_end = lstart + lsize - 1;
337 0 : db_lc = lstart;
338 0 : db_le = lstart;
339 :
340 0 : while (!db_inputchar(cngetc()))
341 0 : continue;
342 :
343 0 : db_putchar('\n'); /* synch output position */
344 :
345 0 : *db_le = 0;
346 0 : return (db_le - db_lbuf_start);
347 : }
|