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 /*      $NetBSD: db_input.c,v 1.28 2020/10/30 06:57:08 skrll Exp $      */
    2 
    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 "AS IS"
   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  *      Author: David B. Golub, Carnegie Mellon University
   29  *      Date:   7/90
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: db_input.c,v 1.28 2020/10/30 06:57:08 skrll Exp $");
   34 
   35 #ifdef _KERNEL_OPT
   36 #include "opt_ddbparam.h"
   37 #endif
   38 
   39 #include <sys/param.h>
   40 #include <sys/proc.h>
   41 
   42 #include <ddb/ddb.h>
   43 
   44 #include <dev/cons.h>
   45 
   46 #ifndef DDB_HISTORY_SIZE
   47 #define DDB_HISTORY_SIZE 0
   48 #endif /* DDB_HISTORY_SIZE */
   49 
   50 /*
   51  * Character input and editing.
   52  */
   53 
   54 /*
   55  * We don't track output position while editing input,
   56  * since input always ends with a new-line.  We just
   57  * reset the line position at the end.
   58  */
   59 static char    *db_lbuf_start;  /* start of input line buffer */
   60 static char    *db_lbuf_end;    /* end of input line buffer */
   61 static char    *db_lc;          /* current character */
   62 static char    *db_le;          /* one past last character */
   63 #if DDB_HISTORY_SIZE != 0
   64 static char     db_history[DDB_HISTORY_SIZE];   /* start of history buffer */
   65 static char    *db_history_curr = db_history;   /* start of current line */
   66 static char    *db_history_last = db_history;   /* start of last line */
   67 static char    *db_history_prev = (char *) 0;   /* start of previous line */
   68 #endif
   69 
   70 
   71 #define CTRL(c)         ((c) & 0x1f)
   72 #define isspace(c)      ((c) == ' ' || (c) == '\t')
   73 #define BLANK           ' '
   74 #define BACKUP          '\b'
   75 
   76 static int      cnmaygetc(void);
   77 static void     db_putstring(const char *, int);
   78 static void     db_putnchars(int, int);
   79 static void     db_delete(int, int);
   80 static void     db_delete_line(void);
   81 static int      db_inputchar(int);
   82 
   83 static void
   84 db_putstring(const char *s, int count)
   85 {
   86 
   87         while (--count >= 0)
   88                 cnputc(*s++);
   89 }
   90 
   91 static void
   92 db_putnchars(int c, int count)
   93 {
   94 
   95         while (--count >= 0)
   96                 cnputc(c);
   97 }
   98 
   99 /*
  100  * Delete N characters, forward or backward
  101  */
  102 #define DEL_FWD         0
  103 #define DEL_BWD         1
  104 static void
  105 db_delete(int n, int bwd)
  106 {
  107         char *p;
  108 
  109         if (bwd) {
  110                 db_lc -= n;
  111                 db_putnchars(BACKUP, n);
  112         }
  113         for (p = db_lc; p < db_le-n; p++) {
  114                 *p = *(p+n);
  115                 cnputc(*p);
  116         }
  117         db_putnchars(BLANK, n);
  118         db_putnchars(BACKUP, db_le - db_lc);
  119         db_le -= n;
  120 }
  121 
  122 static void
  123 db_delete_line(void)
  124 {
  125 
  126         db_delete(db_le - db_lc, DEL_FWD);
  127         db_delete(db_lc - db_lbuf_start, DEL_BWD);
  128         db_le = db_lc = db_lbuf_start;
  129 }
  130 
  131 #if DDB_HISTORY_SIZE != 0
  132 
  133 #define INC_DB_CURR() do {                                              \
  134         ++db_history_curr;                                              \
  135         if (db_history_curr > db_history + DDB_HISTORY_SIZE - 1)        \
  136                 db_history_curr = db_history;                           \
  137     } while (0)
  138 #define DEC_DB_CURR() do {                                              \
  139         --db_history_curr;                                              \
  140         if (db_history_curr < db_history)                               \
  141                 db_history_curr = db_history + DDB_HISTORY_SIZE - 1;    \
  142     } while (0)
  143 
  144 static inline void
  145 db_hist_put(int c)
  146 {
  147         KASSERT(&db_history[0]  <= db_history_last);
  148         KASSERT(db_history_last <= &db_history[DDB_HISTORY_SIZE-1]);
  149 
  150         *db_history_last++ = c;
  151 
  152         if (db_history_last > &db_history[DDB_HISTORY_SIZE-1])
  153             db_history_last = db_history;
  154 }
  155 #endif
  156 
  157 
  158 /* returns true at end-of-line */
  159 static int
  160 db_inputchar(int c)
  161 {
  162         switch (c) {
  163         case CTRL('b'):
  164                 /* back up one character */
  165                 if (db_lc > db_lbuf_start) {
  166                         cnputc(BACKUP);
  167                         db_lc--;
  168                 }
  169                 break;
  170         case CTRL('f'):
  171                 /* forward one character */
  172                 if (db_lc < db_le) {
  173                         cnputc(*db_lc);
  174                         db_lc++;
  175                 }
  176                 break;
  177         case CTRL('a'):
  178                 /* beginning of line */
  179                 while (db_lc > db_lbuf_start) {
  180                         cnputc(BACKUP);
  181                         db_lc--;
  182                 }
  183                 break;
  184         case CTRL('e'):
  185                 /* end of line */
  186                 while (db_lc < db_le) {
  187                         cnputc(*db_lc);
  188                         db_lc++;
  189                 }
  190                 break;
  191         case CTRL('h'):
  192         case 0177:
  193                 /* erase previous character */
  194                 if (db_lc > db_lbuf_start)
  195                         db_delete(1, DEL_BWD);
  196                 break;
  197         case CTRL('d'):
  198                 /* erase next character */
  199                 if (db_lc < db_le)
  200                         db_delete(1, DEL_FWD);
  201                 break;
  202         case CTRL('k'):
  203                 /* delete to end of line */
  204                 if (db_lc < db_le)
  205                         db_delete(db_le - db_lc, DEL_FWD);
  206                 break;
  207         case CTRL('u'):
  208                 /* delete line */
  209                 db_delete_line();
  210                 break;
  211         case CTRL('t'):
  212                 /* twiddle last 2 characters */
  213                 if (db_lc >= db_lbuf_start + 1) {
  214                         if (db_lc < db_le) {
  215                                 c = db_lc[-1];
  216                                 db_lc[-1] = db_lc[0];
  217                                 db_lc[0] = c;
  218                                 cnputc(BACKUP);
  219                                 cnputc(db_lc[-1]);
  220                                 cnputc(db_lc[0]);
  221                                 db_lc++;
  222                         } else if (db_lc >= db_lbuf_start + 2) {
  223                                 c = db_lc[-2];
  224                                 db_lc[-2] = db_lc[-1];
  225                                 db_lc[-1] = c;
  226                                 cnputc(BACKUP);
  227                                 cnputc(BACKUP);
  228                                 cnputc(db_lc[-2]);
  229                                 cnputc(db_lc[-1]);
  230                         }
  231                 }
  232                 break;
  233 #if DDB_HISTORY_SIZE != 0
  234         case CTRL('p'):
  235                 DEC_DB_CURR();
  236                 while (db_history_curr != db_history_last) {
  237                         DEC_DB_CURR();
  238                         if (*db_history_curr == '\0')
  239                                 break;
  240                 }
  241                 db_delete_line();
  242                 if (db_history_curr == db_history_last) {
  243                         INC_DB_CURR();
  244                         db_le = db_lc = db_lbuf_start;
  245                 } else {
  246                         char *p;
  247                         INC_DB_CURR();
  248                         for (p = db_history_curr, db_le = db_lbuf_start;
  249                              *p; ) {
  250                                 *db_le++ = *p++;
  251                                 if (p >= db_history + DDB_HISTORY_SIZE) {
  252                                         p = db_history;
  253                                 }
  254                         }
  255                         db_lc = db_le;
  256                 }
  257                 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  258                 break;
  259         case CTRL('n'):
  260                 while (db_history_curr != db_history_last) {
  261                         if (*db_history_curr == '\0')
  262                                 break;
  263                         INC_DB_CURR();
  264                 }
  265                 if (db_history_curr != db_history_last) {
  266                         INC_DB_CURR();
  267                         db_delete_line();
  268                         if (db_history_curr != db_history_last) {
  269                                 char *p;
  270                                 for (p = db_history_curr,
  271                                      db_le = db_lbuf_start; *p;) {
  272                                         *db_le++ = *p++;
  273                                         if (p >= db_history + DDB_HISTORY_SIZE) {
  274                                                 p = db_history;
  275                                         }
  276                                 }
  277                                 db_lc = db_le;
  278                         }
  279                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  280                 }
  281                 break;
  282 #endif
  283         case CTRL('r'):
  284                 db_putstring("^R\n", 3);
  285                 if (db_le > db_lbuf_start) {
  286                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  287                         db_putnchars(BACKUP, db_le - db_lc);
  288                 }
  289                 break;
  290         case '\n':
  291         case '\r':
  292 #if DDB_HISTORY_SIZE != 0
  293                 /* Check if it same than previous line */
  294                 if (db_history_curr == db_history_prev) {
  295                         char *pp, *pc;
  296 
  297                         /* Is it unmodified */
  298                         for (pp = db_history_prev, pc = db_lbuf_start;
  299                              pc != db_le && *pp; pp++, pc++) {
  300                                 if (*pp != *pc)
  301                                         break;
  302                                 if (++pp >= db_history + DDB_HISTORY_SIZE) {
  303                                         pp = db_history;
  304                                 }
  305                                 if (++pc >= db_history + DDB_HISTORY_SIZE) {
  306                                         pc = db_history;
  307                                 }
  308                         }
  309                         if (!*pp && pc == db_le) {
  310                                 /* Repeted previous line, not saved */
  311                                 db_history_curr = db_history_last;
  312                                 *db_le++ = c;
  313                                 return (true);
  314                         }
  315                 }
  316                 if (db_le != db_lbuf_start) {
  317                         char *p;
  318 
  319                         db_history_prev = db_history_last;
  320 
  321                         for (p = db_lbuf_start; p != db_le; ) {
  322                                 db_hist_put(*p++);
  323                         }
  324                         db_hist_put(0);
  325                 }
  326                 db_history_curr = db_history_last;
  327 #endif
  328                 *db_le++ = c;
  329                 return (1);
  330         default:
  331                 if (db_le == db_lbuf_end) {
  332                         cnputc('\007');
  333                 }
  334                 else if (c >= ' ' && c <= '~') {
  335                         char *p;
  336 
  337                         for (p = db_le; p > db_lc; p--)
  338                                 *p = *(p-1);
  339                         *db_lc++ = c;
  340                         db_le++;
  341                         cnputc(c);
  342                         db_putstring(db_lc, db_le - db_lc);
  343                         db_putnchars(BACKUP, db_le - db_lc);
  344                 }
  345                 break;
  346         }
  347         return (0);
  348 }
  349 
  350 int
  351 db_readline(char *lstart, int lsize)
  352 {
  353 
  354         db_force_whitespace();  /* synch output position */
  355 
  356         db_lbuf_start = lstart;
  357         db_lbuf_end   = lstart + lsize;
  358         db_lc = lstart;
  359         db_le = lstart;
  360 
  361         while (!db_inputchar(cngetc()))
  362                 continue;
  363 
  364         db_putchar('\n');       /* synch output position */
  365 
  366         *db_le = 0;
  367         return (db_le - db_lbuf_start);
  368 }
  369 
  370 void
  371 db_check_interrupt(void)
  372 {
  373         int     c;
  374 
  375         c = cnmaygetc();
  376         switch (c) {
  377         case -1:                /* no character */
  378                 return;
  379 
  380         case CTRL('c'):
  381                 db_error((char *)0);
  382                 /*NOTREACHED*/
  383 
  384         case CTRL('s'):
  385                 do {
  386                         c = cnmaygetc();
  387                         if (c == CTRL('c')) {
  388                                 db_error((char *)0);
  389                                 /*NOTREACHED*/
  390                         }
  391                 } while (c != CTRL('q'));
  392                 break;
  393 
  394         default:
  395                 /* drop on floor */
  396                 break;
  397         }
  398 }
  399 
  400 static int
  401 cnmaygetc(void)
  402 {
  403 
  404         return (-1);
  405 }

Cache object: 0d725158a70764fa6a01697887ec4287


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