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  * Mach Operating System
    3  * Copyright (c) 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
   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 the
   24  * rights to redistribute these changes.
   25  *
   26  * $FreeBSD: src/sys/ddb/db_input.c,v 1.28.2.1 2002/03/08 16:37:10 yar Exp $
   27  * $DragonFly: src/sys/ddb/db_input.c,v 1.5 2005/12/23 21:35:44 swildner Exp $
   28  */
   29 
   30 /*
   31  *      Author: David B. Golub, Carnegie Mellon University
   32  *      Date:   7/90
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/cons.h>
   38 
   39 #include <ddb/ddb.h>
   40 #include <ddb/db_output.h>
   41 
   42 /*
   43  * Character input and editing.
   44  */
   45 
   46 /*
   47  * We don't track output position while editing input,
   48  * since input always ends with a new-line.  We just
   49  * reset the line position at the end.
   50  */
   51 static char *   db_lbuf_start;  /* start of input line buffer */
   52 static char *   db_lbuf_end;    /* end of input line buffer */
   53 static char *   db_lc;          /* current character */
   54 static char *   db_le;          /* one past last character */
   55 
   56 /*
   57  * Simple input line history support.
   58  */
   59 static char     db_lhistory[2048];
   60 static int      db_lhistlsize, db_lhistidx, db_lhistcur;
   61 static int      db_lhist_nlines;
   62 
   63 #define CTRL(c)         ((c) & 0x1f)
   64 #define BLANK           ' '
   65 #define BACKUP          '\b'
   66 
   67 static int      cnmaygetc (void);
   68 static void     db_delete (int n, int bwd);
   69 static int      db_inputchar (int c);
   70 static void     db_putnchars (int c, int count);
   71 static void     db_putstring (char *s, int count);
   72 
   73 void
   74 db_putstring(char *s, int count)
   75 {
   76         while (--count >= 0)
   77             cnputc(*s++);
   78 }
   79 
   80 void
   81 db_putnchars(int c, int count)
   82 {
   83         while (--count >= 0)
   84             cnputc(c);
   85 }
   86 
   87 /*
   88  * Delete N characters, forward or backward
   89  */
   90 #define DEL_FWD         0
   91 #define DEL_BWD         1
   92 void
   93 db_delete(int n, int bwd)
   94 {
   95         char *p;
   96 
   97         if (bwd) {
   98             db_lc -= n;
   99             db_putnchars(BACKUP, n);
  100         }
  101         for (p = db_lc; p < db_le-n; p++) {
  102             *p = *(p+n);
  103             cnputc(*p);
  104         }
  105         db_putnchars(BLANK, n);
  106         db_putnchars(BACKUP, db_le - db_lc);
  107         db_le -= n;
  108 }
  109 
  110 /* returns TRUE at end-of-line */
  111 int
  112 db_inputchar(int c)
  113 {
  114         static int escstate;
  115 
  116         if (escstate == 1) {
  117                 /* ESC seen, look for [ or O */
  118                 if (c == '[' || c == 'O')
  119                         escstate++;
  120                 else
  121                         escstate = 0; /* re-init state machine */
  122                 return (0);
  123         } else if (escstate == 2) {
  124                 escstate = 0;
  125                 /*
  126                  * If a valid cursor key has been found, translate
  127                  * into an emacs-style control key, and fall through.
  128                  * Otherwise, drop off.
  129                  */
  130                 switch (c) {
  131                 case 'A':       /* up */
  132                         c = CTRL('p');
  133                         break;
  134                 case 'B':       /* down */
  135                         c = CTRL('n');
  136                         break;
  137                 case 'C':       /* right */
  138                         c = CTRL('f');
  139                         break;
  140                 case 'D':       /* left */
  141                         c = CTRL('b');
  142                         break;
  143                 default:
  144                         return (0);
  145                 }
  146         }
  147 
  148         switch (c) {
  149             case CTRL('['):
  150                 escstate = 1;
  151                 break;
  152             case CTRL('b'):
  153                 /* back up one character */
  154                 if (db_lc > db_lbuf_start) {
  155                     cnputc(BACKUP);
  156                     db_lc--;
  157                 }
  158                 break;
  159             case CTRL('f'):
  160                 /* forward one character */
  161                 if (db_lc < db_le) {
  162                     cnputc(*db_lc);
  163                     db_lc++;
  164                 }
  165                 break;
  166             case CTRL('a'):
  167                 /* beginning of line */
  168                 while (db_lc > db_lbuf_start) {
  169                     cnputc(BACKUP);
  170                     db_lc--;
  171                 }
  172                 break;
  173             case CTRL('e'):
  174                 /* end of line */
  175                 while (db_lc < db_le) {
  176                     cnputc(*db_lc);
  177                     db_lc++;
  178                 }
  179                 break;
  180             case CTRL('h'):
  181             case 0177:
  182                 /* erase previous character */
  183                 if (db_lc > db_lbuf_start)
  184                     db_delete(1, DEL_BWD);
  185                 break;
  186             case CTRL('d'):
  187                 /* erase next character */
  188                 if (db_lc < db_le)
  189                     db_delete(1, DEL_FWD);
  190                 break;
  191             case CTRL('u'):
  192                 /* kill entire line: */
  193                 /* at first, delete to beginning of line */
  194                 if (db_lc > db_lbuf_start)
  195                     db_delete(db_lc - db_lbuf_start, DEL_BWD);
  196                 /* FALLTHROUGH */
  197             case CTRL('k'):
  198                 /* delete to end of line */
  199                 if (db_lc < db_le)
  200                     db_delete(db_le - db_lc, DEL_FWD);
  201                 break;
  202             case CTRL('t'):
  203                 /* twiddle last 2 characters */
  204                 if (db_lc >= db_lbuf_start + 2) {
  205                     c = db_lc[-2];
  206                     db_lc[-2] = db_lc[-1];
  207                     db_lc[-1] = c;
  208                     cnputc(BACKUP);
  209                     cnputc(BACKUP);
  210                     cnputc(db_lc[-2]);
  211                     cnputc(db_lc[-1]);
  212                 }
  213                 break;
  214             case CTRL('r'):
  215                 db_putstring("^R\n", 3);
  216             redraw:
  217                 if (db_le > db_lbuf_start) {
  218                     db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  219                     db_putnchars(BACKUP, db_le - db_lc);
  220                 }
  221                 break;
  222             case CTRL('p'):
  223                 /* Make previous history line the active one. */
  224                 if (db_lhistcur >= 0) {
  225                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
  226                           db_lbuf_start, db_lhistlsize);
  227                     db_lhistcur--;
  228                     goto hist_redraw;
  229                 }
  230                 break;
  231             case CTRL('n'):
  232                 /* Make next history line the active one. */
  233                 if (db_lhistcur < db_lhistidx - 1) {
  234                     db_lhistcur += 2;
  235                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
  236                           db_lbuf_start, db_lhistlsize);
  237                 } else {
  238                     /*
  239                      * ^N through tail of history, reset the
  240                      * buffer to zero length.
  241                      */
  242                     *db_lbuf_start = '\0';
  243                     db_lhistcur = db_lhistidx;
  244                 }
  245 
  246             hist_redraw:
  247                 db_putnchars(BACKUP, db_le - db_lbuf_start);
  248                 db_putnchars(BLANK, db_le - db_lbuf_start);
  249                 db_putnchars(BACKUP, db_le - db_lbuf_start);
  250                 db_le = index(db_lbuf_start, '\0');
  251                 if (db_le[-1] == '\r' || db_le[-1] == '\n')
  252                     *--db_le = '\0';
  253                 db_lc = db_le;
  254                 goto redraw;
  255 
  256             case -1:
  257                 /*
  258                  * eek! the console returned eof.
  259                  * probably that means we HAVE no console.. we should try bail
  260                  * XXX
  261                  */
  262                 return (0);
  263             case '\n':
  264             case '\r':
  265                 *db_le++ = c;
  266                 return (1);
  267             default:
  268                 if (db_le == db_lbuf_end) {
  269                     cnputc('\007');
  270                 }
  271                 else if (c >= ' ' && c <= '~') {
  272                     char *p;
  273 
  274                     for (p = db_le; p > db_lc; p--)
  275                         *p = *(p-1);
  276                     *db_lc++ = c;
  277                     db_le++;
  278                     cnputc(c);
  279                     db_putstring(db_lc, db_le - db_lc);
  280                     db_putnchars(BACKUP, db_le - db_lc);
  281                 }
  282                 break;
  283         }
  284         return (0);
  285 }
  286 
  287 int
  288 cnmaygetc(void)
  289 {
  290         return (-1);
  291 }
  292 
  293 int
  294 db_readline(char *lstart, int lsize)
  295 {
  296         if (lsize != db_lhistlsize) {
  297                 /*
  298                  * (Re)initialize input line history.  Throw away any
  299                  * existing history.
  300                  */
  301                 db_lhist_nlines = sizeof(db_lhistory) / lsize;
  302                 db_lhistlsize = lsize;
  303                 db_lhistidx = -1;
  304         }
  305         db_lhistcur = db_lhistidx;
  306 
  307         db_force_whitespace();  /* synch output position */
  308 
  309         db_lbuf_start = lstart;
  310         db_lbuf_end   = lstart + lsize;
  311         db_lc = lstart;
  312         db_le = lstart;
  313 
  314         while (!db_inputchar(cngetc()))
  315             continue;
  316 
  317         db_printf("\n");        /* synch output position */
  318         *db_le = 0;
  319 
  320         if (db_le - db_lbuf_start > 1) {
  321             /* Maintain input line history for non-empty lines. */
  322             if (++db_lhistidx == db_lhist_nlines) {
  323                 /* Rotate history. */
  324                 ovbcopy(db_lhistory + db_lhistlsize, db_lhistory,
  325                         db_lhistlsize * (db_lhist_nlines - 1));
  326                 db_lhistidx--;
  327             }
  328             bcopy(lstart, db_lhistory + db_lhistidx * db_lhistlsize,
  329                   db_lhistlsize);
  330         }
  331 
  332         return (db_le - db_lbuf_start);
  333 }
  334 
  335 void
  336 db_check_interrupt(void)
  337 {
  338         int     c;
  339 
  340         c = cnmaygetc();
  341         switch (c) {
  342             case -1:            /* no character */
  343                 return;
  344 
  345             case CTRL('c'):
  346                 db_error(NULL);
  347                 /*NOTREACHED*/
  348 
  349             case CTRL('s'):
  350                 do {
  351                     c = cnmaygetc();
  352                     if (c == CTRL('c'))
  353                         db_error(NULL);
  354                 } while (c != CTRL('q'));
  355                 break;
  356 
  357             default:
  358                 /* drop on floor */
  359                 break;
  360         }
  361 }

Cache object: 6e9222025167c8a803cc0b5e0fe891c3


[ 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.