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

Cache object: b42ff21a9d4d3540dbc057f71481f481


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