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 /*
   27  *      Author: David B. Golub, Carnegie Mellon University
   28  *      Date:   7/90
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/11.2/sys/ddb/db_input.c 324266 2017-10-04 11:54:15Z trasz $");
   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         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             case CTRL('c'):
  199                 /* kill entire line: */
  200                 /* at first, delete to beginning of line */
  201                 if (db_lc > db_lbuf_start)
  202                     db_delete(db_lc - db_lbuf_start, DEL_BWD);
  203                 /* FALLTHROUGH */
  204             case CTRL('k'):
  205                 /* delete to end of line */
  206                 if (db_lc < db_le)
  207                     db_delete(db_le - db_lc, DEL_FWD);
  208                 break;
  209             case CTRL('t'):
  210                 /* twiddle last 2 characters */
  211                 if (db_lc >= db_lbuf_start + 2) {
  212                     c = db_lc[-2];
  213                     db_lc[-2] = db_lc[-1];
  214                     db_lc[-1] = c;
  215                     cnputc(BACKUP);
  216                     cnputc(BACKUP);
  217                     cnputc(db_lc[-2]);
  218                     cnputc(db_lc[-1]);
  219                 }
  220                 break;
  221             case CTRL('w'):
  222                 /* erase previous word */
  223                 for (; db_lc > db_lbuf_start;) {
  224                     if (*(db_lc - 1) != ' ')
  225                         break;
  226                     db_delete(1, DEL_BWD);
  227                 }
  228                 for (; db_lc > db_lbuf_start;) {
  229                     if (*(db_lc - 1) == ' ')
  230                         break;
  231                     db_delete(1, DEL_BWD);
  232                 }
  233                 break;
  234             case CTRL('r'):
  235                 db_putstring("^R\n", 3);
  236             redraw:
  237                 if (db_le > db_lbuf_start) {
  238                     db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  239                     db_putnchars(BACKUP, db_le - db_lc);
  240                 }
  241                 break;
  242             case CTRL('p'):
  243                 /* Make previous history line the active one. */
  244                 if (db_lhistcur >= 0) {
  245                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
  246                           db_lbuf_start, db_lhistlsize);
  247                     db_lhistcur--;
  248                     goto hist_redraw;
  249                 }
  250                 break;
  251             case CTRL('n'):
  252                 /* Make next history line the active one. */
  253                 if (db_lhistcur < db_lhistidx - 1) {
  254                     db_lhistcur += 2;
  255                     bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
  256                           db_lbuf_start, db_lhistlsize);
  257                 } else {
  258                     /*
  259                      * ^N through tail of history, reset the
  260                      * buffer to zero length.
  261                      */
  262                     *db_lbuf_start = '\0';
  263                     db_lhistcur = db_lhistidx;
  264                 }
  265 
  266             hist_redraw:
  267                 db_putnchars(BACKUP, db_lc - db_lbuf_start);
  268                 db_putnchars(BLANK, db_le - db_lbuf_start);
  269                 db_putnchars(BACKUP, db_le - db_lbuf_start);
  270                 db_le = strchr(db_lbuf_start, '\0');
  271                 if (db_le[-1] == '\r' || db_le[-1] == '\n')
  272                     *--db_le = '\0';
  273                 db_lc = db_le;
  274                 goto redraw;
  275 
  276             case -1:
  277                 /*
  278                  * eek! the console returned eof.
  279                  * probably that means we HAVE no console.. we should try bail
  280                  * XXX
  281                  */
  282                 c = '\r';
  283             case '\n':
  284                 /* FALLTHROUGH */
  285             case '\r':
  286                 *db_le++ = c;
  287                 return (1);
  288             default:
  289                 if (db_le == db_lbuf_end) {
  290                     cnputc('\007');
  291                 }
  292                 else if (c >= ' ' && c <= '~') {
  293                     char *p;
  294 
  295                     for (p = db_le; p > db_lc; p--)
  296                         *p = *(p-1);
  297                     *db_lc++ = c;
  298                     db_le++;
  299                     cnputc(c);
  300                     db_putstring(db_lc, db_le - db_lc);
  301                     db_putnchars(BACKUP, db_le - db_lc);
  302                 }
  303                 break;
  304         }
  305         return (0);
  306 }
  307 
  308 static int
  309 cnmaygetc()
  310 {
  311         return (-1);
  312 }
  313 
  314 int
  315 db_readline(lstart, lsize)
  316         char *  lstart;
  317         int     lsize;
  318 {
  319 
  320         if (lsize < 2)
  321                 return (0);
  322         if (lsize != db_lhistlsize) {
  323                 /*
  324                  * (Re)initialize input line history.  Throw away any
  325                  * existing history.
  326                  */
  327                 db_lhist_nlines = sizeof(db_lhistory) / lsize;
  328                 db_lhistlsize = lsize;
  329                 db_lhistidx = -1;
  330         }
  331         db_lhistcur = db_lhistidx;
  332 
  333         db_force_whitespace();  /* synch output position */
  334 
  335         db_lbuf_start = lstart;
  336         db_lbuf_end   = lstart + lsize - 2;     /* Will append NL and NUL. */
  337         db_lc = lstart;
  338         db_le = lstart;
  339 
  340         while (!db_inputchar(cngetc()))
  341             continue;
  342 
  343         db_capture_write(lstart, db_le - db_lbuf_start);
  344         db_printf("\n");        /* synch output position */
  345         *db_le = 0;
  346 
  347         if (db_le - db_lbuf_start > 1) {
  348             /* Maintain input line history for non-empty lines. */
  349             if (++db_lhistidx == db_lhist_nlines) {
  350                 /* Rotate history. */
  351                 bcopy(db_lhistory + db_lhistlsize, db_lhistory,
  352                       db_lhistlsize * (db_lhist_nlines - 1));
  353                 db_lhistidx--;
  354             }
  355             bcopy(lstart, db_lhistory + db_lhistidx * db_lhistlsize,
  356                   db_lhistlsize);
  357         }
  358 
  359         return (db_le - db_lbuf_start);
  360 }
  361 
  362 void
  363 db_check_interrupt(void)
  364 {
  365         int     c;
  366 
  367         c = cnmaygetc();
  368         switch (c) {
  369             case -1:            /* no character */
  370                 return;
  371 
  372             case CTRL('c'):
  373                 db_error((char *)0);
  374                 /*NOTREACHED*/
  375 
  376             case CTRL('s'):
  377                 do {
  378                     c = cnmaygetc();
  379                     if (c == CTRL('c'))
  380                         db_error((char *)0);
  381                 } while (c != CTRL('q'));
  382                 break;
  383 
  384             default:
  385                 /* drop on floor */
  386                 break;
  387         }
  388 }

Cache object: 69c12826327a46d6da15d38401e4bc77


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