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