]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/ddb/db_input.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / sys / ddb / db_input.c
1 /*-
2  * SPDX-License-Identifier: MIT-CMU
3  *
4  * Mach Operating System
5  * Copyright (c) 1991,1990 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie the
26  * rights to redistribute these changes.
27  */
28 /*
29  *      Author: David B. Golub, Carnegie Mellon University
30  *      Date:   7/90
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/cons.h>
39
40 #include <ddb/ddb.h>
41 #include <ddb/db_output.h>
42
43 /*
44  * Character input and editing.
45  */
46
47 /*
48  * We don't track output position while editing input,
49  * since input always ends with a new-line.  We just
50  * reset the line position at the end.
51  */
52 static char *   db_lbuf_start;  /* start of input line buffer */
53 static char *   db_lbuf_end;    /* end of input line buffer */
54 static char *   db_lc;          /* current character */
55 static char *   db_le;          /* one past last character */
56
57 /*
58  * Simple input line history support.
59  */
60 static char     db_lhistory[2048];
61 static int      db_lhistlsize, db_lhistidx, db_lhistcur;
62 static int      db_lhist_nlines;
63
64 #define CTRL(c)         ((c) & 0x1f)
65 #define BLANK           ' '
66 #define BACKUP          '\b'
67
68 static int      cnmaygetc(void);
69 static void     db_delete(int n, int bwd);
70 static int      db_inputchar(int c);
71 static void     db_putnchars(int c, int count);
72 static void     db_putstring(char *s, int count);
73
74 static void
75 db_putstring(s, count)
76         char    *s;
77         int     count;
78 {
79         while (--count >= 0)
80             cnputc(*s++);
81 }
82
83 static void
84 db_putnchars(c, count)
85         int     c;
86         int     count;
87 {
88         while (--count >= 0)
89             cnputc(c);
90 }
91
92 /*
93  * Delete N characters, forward or backward
94  */
95 #define DEL_FWD         0
96 #define DEL_BWD         1
97 static void
98 db_delete(n, bwd)
99         int     n;
100         int     bwd;
101 {
102         char *p;
103
104         if (bwd) {
105             db_lc -= n;
106             db_putnchars(BACKUP, n);
107         }
108         for (p = db_lc; p < db_le-n; p++) {
109             *p = *(p+n);
110             cnputc(*p);
111         }
112         db_putnchars(BLANK, n);
113         db_putnchars(BACKUP, db_le - db_lc);
114         db_le -= n;
115 }
116
117 /* returns true at end-of-line */
118 static int
119 db_inputchar(c)
120         int     c;
121 {
122         static int escstate;
123
124         if (escstate == 1) {
125                 /* ESC seen, look for [ or O */
126                 if (c == '[' || c == 'O')
127                         escstate++;
128                 else
129                         escstate = 0; /* re-init state machine */
130                 return (0);
131         } else if (escstate == 2) {
132                 escstate = 0;
133                 /*
134                  * If a valid cursor key has been found, translate
135                  * into an emacs-style control key, and fall through.
136                  * Otherwise, drop off.
137                  */
138                 switch (c) {
139                 case 'A':       /* up */
140                         c = CTRL('p');
141                         break;
142                 case 'B':       /* down */
143                         c = CTRL('n');
144                         break;
145                 case 'C':       /* right */
146                         c = CTRL('f');
147                         break;
148                 case 'D':       /* left */
149                         c = CTRL('b');
150                         break;
151                 default:
152                         return (0);
153                 }
154         }
155
156         switch (c) {
157             case CTRL('['):
158                 escstate = 1;
159                 break;
160             case CTRL('b'):
161                 /* back up one character */
162                 if (db_lc > db_lbuf_start) {
163                     cnputc(BACKUP);
164                     db_lc--;
165                 }
166                 break;
167             case CTRL('f'):
168                 /* forward one character */
169                 if (db_lc < db_le) {
170                     cnputc(*db_lc);
171                     db_lc++;
172                 }
173                 break;
174             case CTRL('a'):
175                 /* beginning of line */
176                 while (db_lc > db_lbuf_start) {
177                     cnputc(BACKUP);
178                     db_lc--;
179                 }
180                 break;
181             case CTRL('e'):
182                 /* end of line */
183                 while (db_lc < db_le) {
184                     cnputc(*db_lc);
185                     db_lc++;
186                 }
187                 break;
188             case CTRL('h'):
189             case 0177:
190                 /* erase previous character */
191                 if (db_lc > db_lbuf_start)
192                     db_delete(1, DEL_BWD);
193                 break;
194             case CTRL('d'):
195                 /* erase next character */
196                 if (db_lc < db_le)
197                     db_delete(1, DEL_FWD);
198                 break;
199             case CTRL('u'):
200             case CTRL('c'):
201                 /* kill entire line: */
202                 /* at first, delete to beginning of line */
203                 if (db_lc > db_lbuf_start)
204                     db_delete(db_lc - db_lbuf_start, DEL_BWD);
205                 /* FALLTHROUGH */
206             case CTRL('k'):
207                 /* delete to end of line */
208                 if (db_lc < db_le)
209                     db_delete(db_le - db_lc, DEL_FWD);
210                 break;
211             case CTRL('t'):
212                 /* twiddle last 2 characters */
213                 if (db_lc >= db_lbuf_start + 2) {
214                     c = db_lc[-2];
215                     db_lc[-2] = db_lc[-1];
216                     db_lc[-1] = c;
217                     cnputc(BACKUP);
218                     cnputc(BACKUP);
219                     cnputc(db_lc[-2]);
220                     cnputc(db_lc[-1]);
221                 }
222                 break;
223             case CTRL('w'):
224                 /* erase previous word */
225                 for (; db_lc > db_lbuf_start;) {
226                     if (*(db_lc - 1) != ' ')
227                         break;
228                     db_delete(1, DEL_BWD);
229                 }
230                 for (; db_lc > db_lbuf_start;) {
231                     if (*(db_lc - 1) == ' ')
232                         break;
233                     db_delete(1, DEL_BWD);
234                 }
235                 break;
236             case CTRL('r'):
237                 db_putstring("^R\n", 3);
238             redraw:
239                 if (db_le > db_lbuf_start) {
240                     db_putstring(db_lbuf_start, db_le - db_lbuf_start);
241                     db_putnchars(BACKUP, db_le - db_lc);
242                 }
243                 break;
244             case CTRL('p'):
245                 /* Make previous history line the active one. */
246                 if (db_lhistcur >= 0) {
247                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
248                           db_lbuf_start, db_lhistlsize);
249                     db_lhistcur--;
250                     goto hist_redraw;
251                 }
252                 break;
253             case CTRL('n'):
254                 /* Make next history line the active one. */
255                 if (db_lhistcur < db_lhistidx - 1) {
256                     db_lhistcur += 2;
257                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
258                           db_lbuf_start, db_lhistlsize);
259                 } else {
260                     /*
261                      * ^N through tail of history, reset the
262                      * buffer to zero length.
263                      */
264                     *db_lbuf_start = '\0';
265                     db_lhistcur = db_lhistidx;
266                 }
267
268             hist_redraw:
269                 db_putnchars(BACKUP, db_lc - db_lbuf_start);
270                 db_putnchars(BLANK, db_le - db_lbuf_start);
271                 db_putnchars(BACKUP, db_le - db_lbuf_start);
272                 db_le = strchr(db_lbuf_start, '\0');
273                 if (db_le[-1] == '\r' || db_le[-1] == '\n')
274                     *--db_le = '\0';
275                 db_lc = db_le;
276                 goto redraw;
277
278             case -1:
279                 /*
280                  * eek! the console returned eof.
281                  * probably that means we HAVE no console.. we should try bail
282                  * XXX
283                  */
284                 c = '\r';
285             case '\n':
286                 /* FALLTHROUGH */
287             case '\r':
288                 *db_le++ = c;
289                 return (1);
290             default:
291                 if (db_le == db_lbuf_end) {
292                     cnputc('\007');
293                 }
294                 else if (c >= ' ' && c <= '~') {
295                     char *p;
296
297                     for (p = db_le; p > db_lc; p--)
298                         *p = *(p-1);
299                     *db_lc++ = c;
300                     db_le++;
301                     cnputc(c);
302                     db_putstring(db_lc, db_le - db_lc);
303                     db_putnchars(BACKUP, db_le - db_lc);
304                 }
305                 break;
306         }
307         return (0);
308 }
309
310 static int
311 cnmaygetc()
312 {
313         return (-1);
314 }
315
316 int
317 db_readline(lstart, lsize)
318         char *  lstart;
319         int     lsize;
320 {
321
322         if (lsize < 2)
323                 return (0);
324         if (lsize != db_lhistlsize) {
325                 /*
326                  * (Re)initialize input line history.  Throw away any
327                  * existing history.
328                  */
329                 db_lhist_nlines = sizeof(db_lhistory) / lsize;
330                 db_lhistlsize = lsize;
331                 db_lhistidx = -1;
332         }
333         db_lhistcur = db_lhistidx;
334
335         db_force_whitespace();  /* synch output position */
336
337         db_lbuf_start = lstart;
338         db_lbuf_end   = lstart + lsize - 2;     /* Will append NL and NUL. */
339         db_lc = lstart;
340         db_le = lstart;
341
342         while (!db_inputchar(cngetc()))
343             continue;
344
345         db_capture_write(lstart, db_le - db_lbuf_start);
346         db_printf("\n");        /* synch output position */
347         *db_le = 0;
348
349         if (db_le - db_lbuf_start > 1) {
350             /* Maintain input line history for non-empty lines. */
351             if (++db_lhistidx == db_lhist_nlines) {
352                 /* Rotate history. */
353                 bcopy(db_lhistory + db_lhistlsize, db_lhistory,
354                       db_lhistlsize * (db_lhist_nlines - 1));
355                 db_lhistidx--;
356             }
357             bcopy(lstart, db_lhistory + db_lhistidx * db_lhistlsize,
358                   db_lhistlsize);
359         }
360
361         return (db_le - db_lbuf_start);
362 }
363
364 void
365 db_check_interrupt(void)
366 {
367         int     c;
368
369         c = cnmaygetc();
370         switch (c) {
371             case -1:            /* no character */
372                 return;
373
374             case CTRL('c'):
375                 db_error((char *)0);
376                 /*NOTREACHED*/
377
378             case CTRL('s'):
379                 do {
380                     c = cnmaygetc();
381                     if (c == CTRL('c'))
382                         db_error((char *)0);
383                 } while (c != CTRL('q'));
384                 break;
385
386             default:
387                 /* drop on floor */
388                 break;
389         }
390 }