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

Cache object: a57f86a76f6b65d730afbc171d997372


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