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

Cache object: bfb9cb8ce10613a1cc8a4d2dc2f3538c


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