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) 1993,1992,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 "AS IS"
   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 Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_input.c,v $
   29  * Revision 2.12  93/11/17  16:22:31  dbg
   30  *      Added ANSI function prototypes.
   31  *      [93/10/08            dbg]
   32  * 
   33  * Revision 2.11  93/01/14  17:25:02  danner
   34  *      Fixed history code.  In comparing current command line with
   35  *      last, every other character was skipped.
   36  *      [barbou@gr.osf.org]
   37  * 
   38  * Revision 2.10  92/08/03  17:31:21  jfriedl
   39  *      removed silly prototypes
   40  *      [92/08/02            jfriedl]
   41  * 
   42  * Revision 2.9  92/05/21  17:07:05  jfriedl
   43  *      tried prototypes.
   44  *      [92/05/20            jfriedl]
   45  * 
   46  * Revision 2.8  92/02/19  15:07:44  elf
   47  *      Added delete_line (Ctrl-U).
   48  *      [92/02/17            kivinen]
   49  * 
   50  *      Added command line history. Ctrl-P = previous, Ctrl-N = next. If
   51  *      DB_HISTORY_SIZE is 0 then command history is disabled.
   52  *      [92/02/17            kivinen]
   53  * 
   54  * Revision 2.7  91/10/09  16:00:03  af
   55  *      Fixed incorrect db_lbuf_end setting.
   56  *      [91/08/29            tak]
   57  * 
   58  * Revision 2.6  91/07/09  23:15:49  danner
   59  *      Add include of machine/db_machdep.h to allow machine-specific
   60  *       overrides via defines.
   61  *      [91/07/08            danner]
   62  *
   63  * Revision 2.5  91/05/14  15:34:03  mrt
   64  *      Correcting copyright
   65  * 
   66  * Revision 2.4  91/02/14  14:41:53  mrt
   67  *      Add input line editing.
   68  *      [90/11/11            dbg]
   69  * 
   70  * Revision 2.3  91/02/05  17:06:32  mrt
   71  *      Changed to new Mach copyright
   72  *      [91/01/31  16:18:13  mrt]
   73  * 
   74  * Revision 2.2  90/08/27  21:51:03  dbg
   75  *      Reduce lint.
   76  *      [90/08/07            dbg]
   77  *      Created.
   78  *      [90/07/25            dbg]
   79  * 
   80  */
   81 /*
   82  *      Author: David B. Golub, Carnegie Mellon University
   83  *      Date:   7/90
   84  */
   85 #include <mach/boolean.h>
   86 #include <machine/db_machdep.h> /* must come before kern_io.h,
   87                                    since it may override cn* routines */
   88 #include <ddb/db_output.h>
   89 #include <ddb/db_command.h>     /* db_error */
   90 #include <kern/kern_io.h>       /* cn routines */
   91 
   92 
   93 #ifndef DB_HISTORY_SIZE
   94 #define DB_HISTORY_SIZE 4000
   95 #endif
   96 
   97 /*
   98  * Character input and editing.
   99  */
  100 
  101 /*
  102  * We don't track output position while editing input,
  103  * since input always ends with a new-line.  We just
  104  * reset the line position at the end.
  105  */
  106 char *  db_lbuf_start;  /* start of input line buffer */
  107 char *  db_lbuf_end;    /* end of input line buffer */
  108 char *  db_lc;          /* current character */
  109 char *  db_le;          /* one past last character */
  110 #if DB_HISTORY_SIZE != 0
  111 char    db_history[DB_HISTORY_SIZE];    /* start of history buffer */
  112 int     db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
  113 char *  db_history_curr = db_history;   /* start of current line */
  114 char *  db_history_last = db_history;   /* start of last line */
  115 char *  db_history_prev = (char *) 0;   /* start of previous line */
  116 #endif
  117         
  118 #define CTRL(c)         ((c) & 0x1f)
  119 #define isspace(c)      ((c) == ' ' || (c) == '\t')
  120 #define BLANK           ' '
  121 #define BACKUP          '\b'
  122 
  123 void
  124 db_putstring(
  125         char    *s,
  126         int     count)
  127 {
  128         while (--count >= 0)
  129             cnputc(*s++);
  130 }
  131 
  132 void
  133 db_putnchars(
  134         int     c,
  135         int     count)
  136 {
  137         while (--count >= 0)
  138             cnputc(c);
  139 }
  140 
  141 /*
  142  * Delete N characters, forward or backward
  143  */
  144 #define DEL_FWD         0
  145 #define DEL_BWD         1
  146 void
  147 db_delete(
  148         int     n,
  149         int     bwd)
  150 {
  151         register char *p;
  152 
  153         if (bwd) {
  154             db_lc -= n;
  155             db_putnchars(BACKUP, n);
  156         }
  157         for (p = db_lc; p < db_le-n; p++) {
  158             *p = *(p+n);
  159             cnputc(*p);
  160         }
  161         db_putnchars(BLANK, n);
  162         db_putnchars(BACKUP, db_le - db_lc);
  163         db_le -= n;
  164 }
  165 
  166 void
  167 db_delete_line(void)
  168 {
  169         db_delete(db_le - db_lc, DEL_FWD);
  170         db_delete(db_lc - db_lbuf_start, DEL_BWD);
  171         db_le = db_lc = db_lbuf_start;
  172 }
  173 
  174 #if DB_HISTORY_SIZE != 0
  175 #define INC_DB_CURR() \
  176     do { \
  177              db_history_curr++; \
  178              if (db_history_curr > \
  179                  db_history + db_history_size - 1) \
  180                      db_history_curr = db_history; \
  181        } while (0)
  182 #define DEC_DB_CURR() \
  183     do { \
  184              db_history_curr--; \
  185              if (db_history_curr < db_history) \
  186                  db_history_curr = db_history + \
  187                  db_history_size - 1; \
  188        } while (0)
  189 #endif
  190                 
  191 /* returns TRUE at end-of-line */
  192 boolean_t
  193 db_inputchar(
  194         int     c)
  195 {
  196         switch (c) {
  197             case CTRL('b'):
  198                 /* back up one character */
  199                 if (db_lc > db_lbuf_start) {
  200                     cnputc(BACKUP);
  201                     db_lc--;
  202                 }
  203                 break;
  204             case CTRL('f'):
  205                 /* forward one character */
  206                 if (db_lc < db_le) {
  207                     cnputc(*db_lc);
  208                     db_lc++;
  209                 }
  210                 break;
  211             case CTRL('a'):
  212                 /* beginning of line */
  213                 while (db_lc > db_lbuf_start) {
  214                     cnputc(BACKUP);
  215                     db_lc--;
  216                 }
  217                 break;
  218             case CTRL('e'):
  219                 /* end of line */
  220                 while (db_lc < db_le) {
  221                     cnputc(*db_lc);
  222                     db_lc++;
  223                 }
  224                 break;
  225             case CTRL('h'):
  226             case 0177:
  227                 /* erase previous character */
  228                 if (db_lc > db_lbuf_start)
  229                     db_delete(1, DEL_BWD);
  230                 break;
  231             case CTRL('d'):
  232                 /* erase next character */
  233                 if (db_lc < db_le)
  234                     db_delete(1, DEL_FWD);
  235                 break;
  236             case CTRL('k'):
  237                 /* delete to end of line */
  238                 if (db_lc < db_le)
  239                     db_delete(db_le - db_lc, DEL_FWD);
  240                 break;
  241             case CTRL('u'):
  242                 /* delete line */
  243                 db_delete_line();
  244                 break;
  245             case CTRL('t'):
  246                 /* twiddle last 2 characters */
  247                 if (db_lc >= db_lbuf_start + 2) {
  248                     c = db_lc[-2];
  249                     db_lc[-2] = db_lc[-1];
  250                     db_lc[-1] = c;
  251                     cnputc(BACKUP);
  252                     cnputc(BACKUP);
  253                     cnputc(db_lc[-2]);
  254                     cnputc(db_lc[-1]);
  255                 }
  256                 break;
  257 #if DB_HISTORY_SIZE != 0
  258             case CTRL('p'):
  259                 DEC_DB_CURR();
  260                 while (db_history_curr != db_history_last) {
  261                         DEC_DB_CURR();
  262                         if (*db_history_curr == '\0')
  263                             break;
  264                 }
  265                 db_delete_line();
  266                 if (db_history_curr == db_history_last) {
  267                         INC_DB_CURR();
  268                         db_le = db_lc = db_lbuf_start;
  269                 } else {
  270                         register char *p;
  271                         INC_DB_CURR();
  272                         for (p = db_history_curr, db_le = db_lbuf_start;
  273                              *p; ) {
  274                                 *db_le++ = *p++;
  275                                 if (p == db_history + db_history_size) {
  276                                         p = db_history;
  277                                 }
  278                         }
  279                         db_lc = db_le;
  280                 }
  281                 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  282                 break;
  283             case CTRL('n'):
  284                 while (db_history_curr != db_history_last) {
  285                         if (*db_history_curr == '\0')
  286                             break;
  287                         INC_DB_CURR();
  288                 }
  289                 if (db_history_curr != db_history_last) {
  290                         INC_DB_CURR();
  291                         db_delete_line();
  292                         if (db_history_curr != db_history_last) {
  293                                 register char *p;
  294                                 for (p = db_history_curr,
  295                                      db_le = db_lbuf_start; *p;) {
  296                                         *db_le++ = *p++;
  297                                         if (p == db_history +
  298                                             db_history_size) {
  299                                                 p = db_history;
  300                                         }
  301                                 }
  302                                 db_lc = db_le;
  303                         }
  304                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  305                 }
  306                 break;
  307 #endif
  308             case CTRL('r'):
  309                 db_putstring("^R\n", 3);
  310                 if (db_le > db_lbuf_start) {
  311                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  312                         db_putnchars(BACKUP, db_le - db_lc);
  313                 }
  314                 break;
  315             case '\n':
  316             case '\r':
  317 #if DB_HISTORY_SIZE != 0
  318                 /*
  319                  * Check whether current line is the same
  320                  * as previous saved line.  If it is, don`t
  321                  * save it.
  322                  */
  323                 if (db_history_curr == db_history_prev) {
  324                         register char *pp, *pc;
  325 
  326                         /*
  327                          * Is it the same?
  328                          */
  329                         for (pp = db_history_prev, pc = db_lbuf_start;
  330                              pc != db_le && *pp; ) {
  331                                 if (*pp != *pc)
  332                                     break;
  333                                 if (++pp == db_history + db_history_size) {
  334                                         pp = db_history;
  335                                 }
  336                                 pc++;
  337                         }
  338                         if (!*pp && pc == db_le) {
  339                                 /*
  340                                  * Repeated previous line. Don`t save.
  341                                  */
  342                                 db_history_curr = db_history_last;
  343                                 *db_le++ = c;
  344                                 return TRUE;
  345                         }
  346                 }
  347                 if (db_le != db_lbuf_start) {
  348                         register char *p;
  349                         db_history_prev = db_history_last;
  350                         for (p = db_lbuf_start; p != db_le; p++) {
  351                                 *db_history_last++ = *p;
  352                                 if (db_history_last == db_history +
  353                                     db_history_size) {
  354                                         db_history_last = db_history;
  355                                 }
  356                         }
  357                         *db_history_last++ = '\0';
  358                 }
  359                 db_history_curr = db_history_last;
  360 #endif
  361                 *db_le++ = c;
  362                 return TRUE;
  363             default:
  364                 if (db_le == db_lbuf_end) {
  365                     cnputc('\007');
  366                 }
  367                 else if (c >= ' ' && c <= '~') {
  368                     register char *p;
  369 
  370                     for (p = db_le; p > db_lc; p--)
  371                         *p = *(p-1);
  372                     *db_lc++ = c;
  373                     db_le++;
  374                     cnputc(c);
  375                     db_putstring(db_lc, db_le - db_lc);
  376                     db_putnchars(BACKUP, db_le - db_lc);
  377                 }
  378                 break;
  379         }
  380         return FALSE;
  381 }
  382 
  383 int
  384 db_readline(
  385         char *  lstart,
  386         int     lsize)
  387 {
  388         db_force_whitespace();  /* synch output position */
  389 
  390         db_lbuf_start = lstart;
  391         db_lbuf_end   = lstart + lsize - 1;
  392         db_lc = lstart;
  393         db_le = lstart;
  394 
  395         while (!db_inputchar(cngetc()))
  396             continue;
  397 
  398         db_putchar('\n');       /* synch output position */
  399 
  400         *db_le = 0;
  401         return (db_le - db_lbuf_start);
  402 }
  403 
  404 void
  405 db_check_interrupt(void)
  406 {
  407         register int    c;
  408 
  409         c = cnmaygetc();
  410         switch (c) {
  411             case -1:            /* no character */
  412                 return;
  413 
  414             case CTRL('c'):
  415                 db_error((char *)0);
  416                 /*NOTREACHED*/
  417 
  418             case CTRL('s'):
  419                 do {
  420                     c = cnmaygetc();
  421                     if (c == CTRL('c'))
  422                         db_error((char *)0);
  423                 } while (c != CTRL('q'));
  424                 break;
  425 
  426             default:
  427                 /* drop on floor */
  428                 break;
  429         }
  430 }
  431 

Cache object: 49c5e4e0f7b998f343d369a96e582b34


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