The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_input.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 }

Cache object: 3e96ab7de284f42799ab243b6ce01b12


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.