FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_input.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_input.c,v $
29 * Revision 2.12 93/11/17 16:22:31 dbg
30 * Added ANSI function prototypes.
31 * [93/10/08 dbg]
32 *
33 * Revision 2.11 93/01/14 17:25:02 danner
34 * Fixed history code. In comparing current command line with
35 * last, every other character was skipped.
36 * [barbou@gr.osf.org]
37 *
38 * Revision 2.10 92/08/03 17:31:21 jfriedl
39 * removed silly prototypes
40 * [92/08/02 jfriedl]
41 *
42 * Revision 2.9 92/05/21 17:07:05 jfriedl
43 * tried prototypes.
44 * [92/05/20 jfriedl]
45 *
46 * Revision 2.8 92/02/19 15:07:44 elf
47 * Added delete_line (Ctrl-U).
48 * [92/02/17 kivinen]
49 *
50 * Added command line history. Ctrl-P = previous, Ctrl-N = next. If
51 * DB_HISTORY_SIZE is 0 then command history is disabled.
52 * [92/02/17 kivinen]
53 *
54 * Revision 2.7 91/10/09 16:00:03 af
55 * Fixed incorrect db_lbuf_end setting.
56 * [91/08/29 tak]
57 *
58 * Revision 2.6 91/07/09 23:15:49 danner
59 * Add include of machine/db_machdep.h to allow machine-specific
60 * overrides via defines.
61 * [91/07/08 danner]
62 *
63 * Revision 2.5 91/05/14 15:34:03 mrt
64 * Correcting copyright
65 *
66 * Revision 2.4 91/02/14 14:41:53 mrt
67 * Add input line editing.
68 * [90/11/11 dbg]
69 *
70 * Revision 2.3 91/02/05 17:06:32 mrt
71 * Changed to new Mach copyright
72 * [91/01/31 16:18:13 mrt]
73 *
74 * Revision 2.2 90/08/27 21:51:03 dbg
75 * Reduce lint.
76 * [90/08/07 dbg]
77 * Created.
78 * [90/07/25 dbg]
79 *
80 */
81 /*
82 * Author: David B. Golub, Carnegie Mellon University
83 * Date: 7/90
84 */
85 #include <mach/boolean.h>
86 #include <machine/db_machdep.h> /* must come before kern_io.h,
87 since it may override cn* routines */
88 #include <ddb/db_output.h>
89 #include <ddb/db_command.h> /* db_error */
90 #include <kern/kern_io.h> /* cn routines */
91
92
93 #ifndef DB_HISTORY_SIZE
94 #define DB_HISTORY_SIZE 4000
95 #endif
96
97 /*
98 * Character input and editing.
99 */
100
101 /*
102 * We don't track output position while editing input,
103 * since input always ends with a new-line. We just
104 * reset the line position at the end.
105 */
106 char * db_lbuf_start; /* start of input line buffer */
107 char * db_lbuf_end; /* end of input line buffer */
108 char * db_lc; /* current character */
109 char * db_le; /* one past last character */
110 #if DB_HISTORY_SIZE != 0
111 char db_history[DB_HISTORY_SIZE]; /* start of history buffer */
112 int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
113 char * db_history_curr = db_history; /* start of current line */
114 char * db_history_last = db_history; /* start of last line */
115 char * db_history_prev = (char *) 0; /* start of previous line */
116 #endif
117
118 #define CTRL(c) ((c) & 0x1f)
119 #define isspace(c) ((c) == ' ' || (c) == '\t')
120 #define BLANK ' '
121 #define BACKUP '\b'
122
123 void
124 db_putstring(
125 char *s,
126 int count)
127 {
128 while (--count >= 0)
129 cnputc(*s++);
130 }
131
132 void
133 db_putnchars(
134 int c,
135 int count)
136 {
137 while (--count >= 0)
138 cnputc(c);
139 }
140
141 /*
142 * Delete N characters, forward or backward
143 */
144 #define DEL_FWD 0
145 #define DEL_BWD 1
146 void
147 db_delete(
148 int n,
149 int bwd)
150 {
151 register char *p;
152
153 if (bwd) {
154 db_lc -= n;
155 db_putnchars(BACKUP, n);
156 }
157 for (p = db_lc; p < db_le-n; p++) {
158 *p = *(p+n);
159 cnputc(*p);
160 }
161 db_putnchars(BLANK, n);
162 db_putnchars(BACKUP, db_le - db_lc);
163 db_le -= n;
164 }
165
166 void
167 db_delete_line(void)
168 {
169 db_delete(db_le - db_lc, DEL_FWD);
170 db_delete(db_lc - db_lbuf_start, DEL_BWD);
171 db_le = db_lc = db_lbuf_start;
172 }
173
174 #if DB_HISTORY_SIZE != 0
175 #define INC_DB_CURR() \
176 do { \
177 db_history_curr++; \
178 if (db_history_curr > \
179 db_history + db_history_size - 1) \
180 db_history_curr = db_history; \
181 } while (0)
182 #define DEC_DB_CURR() \
183 do { \
184 db_history_curr--; \
185 if (db_history_curr < db_history) \
186 db_history_curr = db_history + \
187 db_history_size - 1; \
188 } while (0)
189 #endif
190
191 /* returns TRUE at end-of-line */
192 boolean_t
193 db_inputchar(
194 int c)
195 {
196 switch (c) {
197 case CTRL('b'):
198 /* back up one character */
199 if (db_lc > db_lbuf_start) {
200 cnputc(BACKUP);
201 db_lc--;
202 }
203 break;
204 case CTRL('f'):
205 /* forward one character */
206 if (db_lc < db_le) {
207 cnputc(*db_lc);
208 db_lc++;
209 }
210 break;
211 case CTRL('a'):
212 /* beginning of line */
213 while (db_lc > db_lbuf_start) {
214 cnputc(BACKUP);
215 db_lc--;
216 }
217 break;
218 case CTRL('e'):
219 /* end of line */
220 while (db_lc < db_le) {
221 cnputc(*db_lc);
222 db_lc++;
223 }
224 break;
225 case CTRL('h'):
226 case 0177:
227 /* erase previous character */
228 if (db_lc > db_lbuf_start)
229 db_delete(1, DEL_BWD);
230 break;
231 case CTRL('d'):
232 /* erase next character */
233 if (db_lc < db_le)
234 db_delete(1, DEL_FWD);
235 break;
236 case CTRL('k'):
237 /* delete to end of line */
238 if (db_lc < db_le)
239 db_delete(db_le - db_lc, DEL_FWD);
240 break;
241 case CTRL('u'):
242 /* delete line */
243 db_delete_line();
244 break;
245 case CTRL('t'):
246 /* twiddle last 2 characters */
247 if (db_lc >= db_lbuf_start + 2) {
248 c = db_lc[-2];
249 db_lc[-2] = db_lc[-1];
250 db_lc[-1] = c;
251 cnputc(BACKUP);
252 cnputc(BACKUP);
253 cnputc(db_lc[-2]);
254 cnputc(db_lc[-1]);
255 }
256 break;
257 #if DB_HISTORY_SIZE != 0
258 case CTRL('p'):
259 DEC_DB_CURR();
260 while (db_history_curr != db_history_last) {
261 DEC_DB_CURR();
262 if (*db_history_curr == '\0')
263 break;
264 }
265 db_delete_line();
266 if (db_history_curr == db_history_last) {
267 INC_DB_CURR();
268 db_le = db_lc = db_lbuf_start;
269 } else {
270 register char *p;
271 INC_DB_CURR();
272 for (p = db_history_curr, db_le = db_lbuf_start;
273 *p; ) {
274 *db_le++ = *p++;
275 if (p == db_history + db_history_size) {
276 p = db_history;
277 }
278 }
279 db_lc = db_le;
280 }
281 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
282 break;
283 case CTRL('n'):
284 while (db_history_curr != db_history_last) {
285 if (*db_history_curr == '\0')
286 break;
287 INC_DB_CURR();
288 }
289 if (db_history_curr != db_history_last) {
290 INC_DB_CURR();
291 db_delete_line();
292 if (db_history_curr != db_history_last) {
293 register char *p;
294 for (p = db_history_curr,
295 db_le = db_lbuf_start; *p;) {
296 *db_le++ = *p++;
297 if (p == db_history +
298 db_history_size) {
299 p = db_history;
300 }
301 }
302 db_lc = db_le;
303 }
304 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
305 }
306 break;
307 #endif
308 case CTRL('r'):
309 db_putstring("^R\n", 3);
310 if (db_le > db_lbuf_start) {
311 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
312 db_putnchars(BACKUP, db_le - db_lc);
313 }
314 break;
315 case '\n':
316 case '\r':
317 #if DB_HISTORY_SIZE != 0
318 /*
319 * Check whether current line is the same
320 * as previous saved line. If it is, don`t
321 * save it.
322 */
323 if (db_history_curr == db_history_prev) {
324 register char *pp, *pc;
325
326 /*
327 * Is it the same?
328 */
329 for (pp = db_history_prev, pc = db_lbuf_start;
330 pc != db_le && *pp; ) {
331 if (*pp != *pc)
332 break;
333 if (++pp == db_history + db_history_size) {
334 pp = db_history;
335 }
336 pc++;
337 }
338 if (!*pp && pc == db_le) {
339 /*
340 * Repeated previous line. Don`t save.
341 */
342 db_history_curr = db_history_last;
343 *db_le++ = c;
344 return TRUE;
345 }
346 }
347 if (db_le != db_lbuf_start) {
348 register char *p;
349 db_history_prev = db_history_last;
350 for (p = db_lbuf_start; p != db_le; p++) {
351 *db_history_last++ = *p;
352 if (db_history_last == db_history +
353 db_history_size) {
354 db_history_last = db_history;
355 }
356 }
357 *db_history_last++ = '\0';
358 }
359 db_history_curr = db_history_last;
360 #endif
361 *db_le++ = c;
362 return TRUE;
363 default:
364 if (db_le == db_lbuf_end) {
365 cnputc('\007');
366 }
367 else if (c >= ' ' && c <= '~') {
368 register char *p;
369
370 for (p = db_le; p > db_lc; p--)
371 *p = *(p-1);
372 *db_lc++ = c;
373 db_le++;
374 cnputc(c);
375 db_putstring(db_lc, db_le - db_lc);
376 db_putnchars(BACKUP, db_le - db_lc);
377 }
378 break;
379 }
380 return FALSE;
381 }
382
383 int
384 db_readline(
385 char * lstart,
386 int lsize)
387 {
388 db_force_whitespace(); /* synch output position */
389
390 db_lbuf_start = lstart;
391 db_lbuf_end = lstart + lsize - 1;
392 db_lc = lstart;
393 db_le = lstart;
394
395 while (!db_inputchar(cngetc()))
396 continue;
397
398 db_putchar('\n'); /* synch output position */
399
400 *db_le = 0;
401 return (db_le - db_lbuf_start);
402 }
403
404 void
405 db_check_interrupt(void)
406 {
407 register int c;
408
409 c = cnmaygetc();
410 switch (c) {
411 case -1: /* no character */
412 return;
413
414 case CTRL('c'):
415 db_error((char *)0);
416 /*NOTREACHED*/
417
418 case CTRL('s'):
419 do {
420 c = cnmaygetc();
421 if (c == CTRL('c'))
422 db_error((char *)0);
423 } while (c != CTRL('q'));
424 break;
425
426 default:
427 /* drop on floor */
428 break;
429 }
430 }
431
Cache object: 49c5e4e0f7b998f343d369a96e582b34
|