root/ddb/db_input.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_putstring
  2. db_putnchars
  3. db_delete
  4. db_delete_line
  5. db_inputchar
  6. db_readline

    1 /*      $OpenBSD: db_input.c,v 1.11 2006/07/06 18:14:14 miod Exp $      */
    2 /*      $NetBSD: db_input.c,v 1.7 1996/02/05 01:57:02 christos Exp $    */
    3 
    4 /* 
    5  * Mach Operating System
    6  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    7  * All Rights Reserved.
    8  * 
    9  * Permission to use, copy, modify and distribute this software and its
   10  * documentation is hereby granted, provided that both the copyright
   11  * notice and this permission notice appear in all copies of the
   12  * software, derivative works or modified versions, and any portions
   13  * thereof, and that both notices appear in supporting documentation.
   14  * 
   15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   18  * 
   19  * Carnegie Mellon requests users of this software to return to
   20  * 
   21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   22  *  School of Computer Science
   23  *  Carnegie Mellon University
   24  *  Pittsburgh PA 15213-3890
   25  * 
   26  * any improvements or extensions that they make and grant Carnegie Mellon
   27  * the rights to redistribute these changes.
   28  *
   29  *      Author: David B. Golub, Carnegie Mellon University
   30  *      Date:   7/90
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/proc.h>
   35 
   36 #include <uvm/uvm_extern.h>
   37 
   38 #include <machine/db_machdep.h>
   39 
   40 #include <ddb/db_var.h>
   41 #include <ddb/db_output.h>
   42 #include <ddb/db_command.h>
   43 #include <ddb/db_sym.h>
   44 #include <ddb/db_extern.h>
   45 
   46 #include <dev/cons.h>
   47 
   48 /*
   49  * Character input and editing.
   50  */
   51 
   52 /*
   53  * We don't track output position while editing input,
   54  * since input always ends with a new-line.  We just
   55  * reset the line position at the end.
   56  */
   57 char *  db_lbuf_start;  /* start of input line buffer */
   58 char *  db_lbuf_end;    /* end of input line buffer */
   59 char *  db_lc;          /* current character */
   60 char *  db_le;          /* one past last character */
   61 #if DB_HISTORY_SIZE != 0
   62 char    db_history[DB_HISTORY_SIZE];    /* start of history buffer */
   63 int     db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
   64 char *  db_history_curr = db_history;   /* start of current line */
   65 char *  db_history_last = db_history;   /* start of last line */
   66 char *  db_history_prev = (char *) 0;   /* start of previous line */
   67 #endif
   68         
   69 
   70 #define CTRL(c)         ((c) & 0x1f)
   71 #define isspace(c)      ((c) == ' ' || (c) == '\t')
   72 #define BLANK           ' '
   73 #define BACKUP          '\b'
   74 
   75 void
   76 db_putstring(char *s, int count)
   77 {
   78         while (--count >= 0)
   79             cnputc(*s++);
   80 }
   81 
   82 void
   83 db_putnchars(int c, int count)
   84 {
   85         while (--count >= 0)
   86             cnputc(c);
   87 }
   88 
   89 /*
   90  * Delete N characters, forward or backward
   91  */
   92 #define DEL_FWD         0
   93 #define DEL_BWD         1
   94 void
   95 db_delete(int n, int bwd)
   96 {
   97         char *p;
   98 
   99         if (bwd) {
  100             db_lc -= n;
  101             db_putnchars(BACKUP, n);
  102         }
  103         for (p = db_lc; p < db_le-n; p++) {
  104             *p = *(p+n);
  105             cnputc(*p);
  106         }
  107         db_putnchars(BLANK, n);
  108         db_putnchars(BACKUP, db_le - db_lc);
  109         db_le -= n;
  110 }
  111 
  112 void
  113 db_delete_line(void)
  114 {
  115         db_delete(db_le - db_lc, DEL_FWD);
  116         db_delete(db_lc - db_lbuf_start, DEL_BWD);
  117         db_le = db_lc = db_lbuf_start;
  118 }
  119 
  120 #if DB_HISTORY_SIZE != 0
  121 #define INC_DB_CURR() \
  122         do { \
  123                 db_history_curr++; \
  124                 if (db_history_curr > \
  125                         db_history + db_history_size - 1) \
  126                         db_history_curr = db_history; \
  127         } while (0)
  128 #define DEC_DB_CURR() \
  129         do { \
  130                 db_history_curr--; \
  131                 if (db_history_curr < db_history) \
  132                         db_history_curr = db_history + \
  133                         db_history_size - 1; \
  134         } while (0)
  135 #endif
  136                 
  137 /* returns TRUE at end-of-line */
  138 int
  139 db_inputchar(int c)
  140 {
  141         switch (c) {
  142             case CTRL('b'):
  143                 /* back up one character */
  144                 if (db_lc > db_lbuf_start) {
  145                     cnputc(BACKUP);
  146                     db_lc--;
  147                 }
  148                 break;
  149             case CTRL('f'):
  150                 /* forward one character */
  151                 if (db_lc < db_le) {
  152                     cnputc(*db_lc);
  153                     db_lc++;
  154                 }
  155                 break;
  156             case CTRL('a'):
  157                 /* beginning of line */
  158                 while (db_lc > db_lbuf_start) {
  159                     cnputc(BACKUP);
  160                     db_lc--;
  161                 }
  162                 break;
  163             case CTRL('e'):
  164                 /* end of line */
  165                 while (db_lc < db_le) {
  166                     cnputc(*db_lc);
  167                     db_lc++;
  168                 }
  169                 break;
  170             case CTRL('w'):
  171                 /* erase word back */
  172                 while (db_lc > db_lbuf_start && db_lc[-1] != BLANK)
  173                     db_delete(1, DEL_BWD);
  174                 break;
  175             case CTRL('h'):
  176             case 0177:
  177                 /* erase previous character */
  178                 if (db_lc > db_lbuf_start)
  179                     db_delete(1, DEL_BWD);
  180                 break;
  181             case CTRL('d'):
  182                 /* erase next character */
  183                 if (db_lc < db_le)
  184                     db_delete(1, DEL_FWD);
  185                 break;
  186             case CTRL('k'):
  187                 /* delete to end of line */
  188                 if (db_lc < db_le)
  189                     db_delete(db_le - db_lc, DEL_FWD);
  190                 break;
  191             case CTRL('u'):
  192                 /* delete line */
  193                 db_delete_line();
  194                 break;
  195             case CTRL('t'):
  196                 /* twiddle last 2 characters */
  197                 if (db_lc >= db_lbuf_start + 2) {
  198                     c = db_lc[-2];
  199                     db_lc[-2] = db_lc[-1];
  200                     db_lc[-1] = c;
  201                     cnputc(BACKUP);
  202                     cnputc(BACKUP);
  203                     cnputc(db_lc[-2]);
  204                     cnputc(db_lc[-1]);
  205                 }
  206                 break;
  207 #if DB_HISTORY_SIZE != 0
  208             case CTRL('p'):
  209                 DEC_DB_CURR();
  210                 while (db_history_curr != db_history_last) {
  211                         DEC_DB_CURR();
  212                         if (*db_history_curr == '\0')
  213                                 break;
  214                 }
  215                 db_delete_line();
  216                 if (db_history_curr == db_history_last) {
  217                         INC_DB_CURR();
  218                         db_le = db_lc = db_lbuf_start;
  219                 } else {
  220                         char *p;
  221                         INC_DB_CURR();
  222                         for (p = db_history_curr, db_le = db_lbuf_start;*p; ) {
  223                                 *db_le++ = *p++;
  224                                 if (p == db_history + db_history_size)
  225                                         p = db_history;
  226                         }
  227                         db_lc = db_le;
  228                 }
  229                 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  230                 break;
  231             case CTRL('n'):
  232                 while (db_history_curr != db_history_last) {
  233                         if (*db_history_curr == '\0')
  234                                 break;
  235                         INC_DB_CURR();
  236                 }
  237                 if (db_history_curr != db_history_last) {
  238                         INC_DB_CURR();
  239                         db_delete_line();
  240                         if (db_history_curr != db_history_last) {
  241                                 char *p;
  242                                 for (p = db_history_curr,
  243                                      db_le = db_lbuf_start; *p;) {
  244                                         *db_le++ = *p++;
  245                                         if (p == db_history + db_history_size)
  246                                                 p = db_history;
  247                                 }
  248                                 db_lc = db_le;
  249                         }
  250                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  251                 }
  252                 break;
  253 #endif
  254             case CTRL('r'):
  255                 db_putstring("^R\n", 3);
  256                 if (db_le > db_lbuf_start) {
  257                         db_putstring(db_lbuf_start, db_le - db_lbuf_start);
  258                         db_putnchars(BACKUP, db_le - db_lc);
  259                 }
  260                 break;
  261             case '\n':
  262             case '\r':
  263 #if DB_HISTORY_SIZE != 0
  264                 /*
  265                  * Check whether current line is the same
  266                  * as previous saved line.  If it is, don`t
  267                  * save it.
  268                  */
  269                 if (db_history_curr == db_history_prev) {
  270                         char *pp, *pc;
  271 
  272                         /*
  273                          * Is it the same?
  274                          */
  275                         for (pp = db_history_prev, pc = db_lbuf_start;
  276                              pc != db_le && *pp; ) {
  277                                 if (*pp != *pc)
  278                                         break;
  279                                 if (++pp == db_history + db_history_size)
  280                                         pp = db_history;
  281                                 pc++;
  282                         }
  283                         if (!*pp && pc == db_le) {
  284                                 /*
  285                                  * Repeated previous line. Don`t save.
  286                                  */
  287                                 db_history_curr = db_history_last;
  288                                 *db_le++ = c;
  289                                 return TRUE;
  290                         }
  291                 }
  292                 if (db_le != db_lbuf_start) {
  293                         char *p;
  294                         db_history_prev = db_history_last;
  295                         for (p = db_lbuf_start; p != db_le; p++) {
  296                                 *db_history_last++ = *p;
  297                                 if (db_history_last ==
  298                                     db_history + db_history_size)
  299                                         db_history_last = db_history;
  300                         }
  301                         *db_history_last++ = '\0';
  302                 }
  303                 db_history_curr = db_history_last;
  304 #endif
  305                 *db_le++ = c;
  306                 return TRUE;
  307             default:
  308                 if (db_le == db_lbuf_end) {
  309                     cnputc('\007');
  310                 }
  311                 else if (c >= ' ' && c <= '~') {
  312                     char *p;
  313 
  314                     for (p = db_le; p > db_lc; p--)
  315                         *p = *(p-1);
  316                     *db_lc++ = c;
  317                     db_le++;
  318                     cnputc(c);
  319                     db_putstring(db_lc, db_le - db_lc);
  320                     db_putnchars(BACKUP, db_le - db_lc);
  321                 }
  322                 break;
  323         }
  324         return FALSE;
  325 }
  326 
  327 int
  328 db_readline(char *lstart, int lsize)
  329 {
  330         db_force_whitespace();  /* synch output position */
  331 
  332         db_lbuf_start = lstart;
  333         db_lbuf_end   = lstart + lsize - 1;
  334         db_lc = lstart;
  335         db_le = lstart;
  336 
  337         while (!db_inputchar(cngetc()))
  338             continue;
  339 
  340         db_putchar('\n');       /* synch output position */
  341 
  342         *db_le = 0;
  343         return (db_le - db_lbuf_start);
  344 }

/* [<][>][^][v][top][bottom][index][help] */