Diff for /qemu/readline.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2018/04/24 16:50:22 version 1.1.1.4, 2018/04/24 17:20:25
Line 21 Line 21
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.   * THE SOFTWARE.
  */   */
 #include "qemu-common.h"  #include "readline.h"
 #include "console.h"  #include "monitor.h"
   
 #define TERM_CMD_BUF_SIZE 4095  
 #define TERM_MAX_CMDS 64  
 #define NB_COMPLETIONS_MAX 256  
   
 #define IS_NORM 0  #define IS_NORM 0
 #define IS_ESC  1  #define IS_ESC  1
Line 34 Line 30
   
 #define printf do_not_use_printf  #define printf do_not_use_printf
   
 static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];  void readline_show_prompt(ReadLineState *rs)
 static int term_cmd_buf_index;  
 static int term_cmd_buf_size;  
   
 static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];  
 static int term_last_cmd_buf_index;  
 static int term_last_cmd_buf_size;  
   
 static int term_esc_state;  
 static int term_esc_param;  
   
 static char *term_history[TERM_MAX_CMDS];  
 static int term_hist_entry = -1;  
   
 static int nb_completions;  
 int completion_index;  
 static char *completions[NB_COMPLETIONS_MAX];  
   
 static ReadLineFunc *term_readline_func;  
 static int term_is_password;  
 static char term_prompt[256];  
 static void *term_readline_opaque;  
   
 static void term_show_prompt2(void)  
 {  
     term_printf("%s", term_prompt);  
     term_flush();  
     term_last_cmd_buf_index = 0;  
     term_last_cmd_buf_size = 0;  
     term_esc_state = IS_NORM;  
 }  
   
 static void term_show_prompt(void)  
 {  {
     term_show_prompt2();      monitor_printf(rs->mon, "%s", rs->prompt);
     term_cmd_buf_index = 0;      monitor_flush(rs->mon);
     term_cmd_buf_size = 0;      rs->last_cmd_buf_index = 0;
       rs->last_cmd_buf_size = 0;
       rs->esc_state = IS_NORM;
 }  }
   
 /* update the displayed command line */  /* update the displayed command line */
 static void term_update(void)  static void readline_update(ReadLineState *rs)
 {  {
     int i, delta, len;      int i, delta, len;
   
     if (term_cmd_buf_size != term_last_cmd_buf_size ||      if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
         memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {          memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
         for(i = 0; i < term_last_cmd_buf_index; i++) {          for(i = 0; i < rs->last_cmd_buf_index; i++) {
             term_printf("\033[D");              monitor_printf(rs->mon, "\033[D");
         }          }
         term_cmd_buf[term_cmd_buf_size] = '\0';          rs->cmd_buf[rs->cmd_buf_size] = '\0';
         if (term_is_password) {          if (rs->read_password) {
             len = strlen(term_cmd_buf);              len = strlen(rs->cmd_buf);
             for(i = 0; i < len; i++)              for(i = 0; i < len; i++)
                 term_printf("*");                  monitor_printf(rs->mon, "*");
         } else {          } else {
             term_printf("%s", term_cmd_buf);              monitor_printf(rs->mon, "%s", rs->cmd_buf);
         }          }
         term_printf("\033[K");          monitor_printf(rs->mon, "\033[K");
         memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);          memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
         term_last_cmd_buf_size = term_cmd_buf_size;          rs->last_cmd_buf_size = rs->cmd_buf_size;
         term_last_cmd_buf_index = term_cmd_buf_size;          rs->last_cmd_buf_index = rs->cmd_buf_size;
     }      }
     if (term_cmd_buf_index != term_last_cmd_buf_index) {      if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
         delta = term_cmd_buf_index - term_last_cmd_buf_index;          delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
         if (delta > 0) {          if (delta > 0) {
             for(i = 0;i < delta; i++) {              for(i = 0;i < delta; i++) {
                 term_printf("\033[C");                  monitor_printf(rs->mon, "\033[C");
             }              }
         } else {          } else {
             delta = -delta;              delta = -delta;
             for(i = 0;i < delta; i++) {              for(i = 0;i < delta; i++) {
                 term_printf("\033[D");                  monitor_printf(rs->mon, "\033[D");
             }              }
         }          }
         term_last_cmd_buf_index = term_cmd_buf_index;          rs->last_cmd_buf_index = rs->cmd_buf_index;
     }      }
     term_flush();      monitor_flush(rs->mon);
 }  }
   
 static void term_insert_char(int ch)  static void readline_insert_char(ReadLineState *rs, int ch)
 {  {
     if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {      if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
         memmove(term_cmd_buf + term_cmd_buf_index + 1,          memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
                 term_cmd_buf + term_cmd_buf_index,                  rs->cmd_buf + rs->cmd_buf_index,
                 term_cmd_buf_size - term_cmd_buf_index);                  rs->cmd_buf_size - rs->cmd_buf_index);
         term_cmd_buf[term_cmd_buf_index] = ch;          rs->cmd_buf[rs->cmd_buf_index] = ch;
         term_cmd_buf_size++;          rs->cmd_buf_size++;
         term_cmd_buf_index++;          rs->cmd_buf_index++;
     }      }
 }  }
   
 static void term_backward_char(void)  static void readline_backward_char(ReadLineState *rs)
 {  {
     if (term_cmd_buf_index > 0) {      if (rs->cmd_buf_index > 0) {
         term_cmd_buf_index--;          rs->cmd_buf_index--;
     }      }
 }  }
   
 static void term_forward_char(void)  static void readline_forward_char(ReadLineState *rs)
 {  {
     if (term_cmd_buf_index < term_cmd_buf_size) {      if (rs->cmd_buf_index < rs->cmd_buf_size) {
         term_cmd_buf_index++;          rs->cmd_buf_index++;
     }      }
 }  }
   
 static void term_delete_char(void)  static void readline_delete_char(ReadLineState *rs)
 {  {
     if (term_cmd_buf_index < term_cmd_buf_size) {      if (rs->cmd_buf_index < rs->cmd_buf_size) {
         memmove(term_cmd_buf + term_cmd_buf_index,          memmove(rs->cmd_buf + rs->cmd_buf_index,
                 term_cmd_buf + term_cmd_buf_index + 1,                  rs->cmd_buf + rs->cmd_buf_index + 1,
                 term_cmd_buf_size - term_cmd_buf_index - 1);                  rs->cmd_buf_size - rs->cmd_buf_index - 1);
         term_cmd_buf_size--;          rs->cmd_buf_size--;
     }      }
 }  }
   
 static void term_backspace(void)  static void readline_backspace(ReadLineState *rs)
 {  {
     if (term_cmd_buf_index > 0) {      if (rs->cmd_buf_index > 0) {
         term_backward_char();          readline_backward_char(rs);
         term_delete_char();          readline_delete_char(rs);
     }      }
 }  }
   
 static void term_backword(void)  static void readline_backword(ReadLineState *rs)
 {  {
     int start;      int start;
   
     if (term_cmd_buf_index == 0 || term_cmd_buf_index > term_cmd_buf_size) {      if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
         return;          return;
     }      }
   
     start = term_cmd_buf_index - 1;      start = rs->cmd_buf_index - 1;
   
     /* find first word (backwards) */      /* find first word (backwards) */
     while (start > 0) {      while (start > 0) {
         if (!qemu_isspace(term_cmd_buf[start])) {          if (!qemu_isspace(rs->cmd_buf[start])) {
             break;              break;
         }          }
   
Line 178  static void term_backword(void) Line 144  static void term_backword(void)
   
     /* find first space (backwards) */      /* find first space (backwards) */
     while (start > 0) {      while (start > 0) {
         if (qemu_isspace(term_cmd_buf[start])) {          if (qemu_isspace(rs->cmd_buf[start])) {
             ++start;              ++start;
             break;              break;
         }          }
Line 187  static void term_backword(void) Line 153  static void term_backword(void)
     }      }
   
     /* remove word */      /* remove word */
     if (start < term_cmd_buf_index) {      if (start < rs->cmd_buf_index) {
         memmove(term_cmd_buf + start,          memmove(rs->cmd_buf + start,
                 term_cmd_buf + term_cmd_buf_index,                  rs->cmd_buf + rs->cmd_buf_index,
                 term_cmd_buf_size - term_cmd_buf_index);                  rs->cmd_buf_size - rs->cmd_buf_index);
         term_cmd_buf_size -= term_cmd_buf_index - start;          rs->cmd_buf_size -= rs->cmd_buf_index - start;
         term_cmd_buf_index = start;          rs->cmd_buf_index = start;
     }      }
 }  }
   
 static void term_bol(void)  static void readline_bol(ReadLineState *rs)
 {  {
     term_cmd_buf_index = 0;      rs->cmd_buf_index = 0;
 }  }
   
 static void term_eol(void)  static void readline_eol(ReadLineState *rs)
 {  {
     term_cmd_buf_index = term_cmd_buf_size;      rs->cmd_buf_index = rs->cmd_buf_size;
 }  }
   
 static void term_up_char(void)  static void readline_up_char(ReadLineState *rs)
 {  {
     int idx;      int idx;
   
     if (term_hist_entry == 0)      if (rs->hist_entry == 0)
         return;          return;
     if (term_hist_entry == -1) {      if (rs->hist_entry == -1) {
         /* Find latest entry */          /* Find latest entry */
         for (idx = 0; idx < TERM_MAX_CMDS; idx++) {          for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
             if (term_history[idx] == NULL)              if (rs->history[idx] == NULL)
                 break;                  break;
         }          }
         term_hist_entry = idx;          rs->hist_entry = idx;
     }      }
     term_hist_entry--;      rs->hist_entry--;
     if (term_hist_entry >= 0) {      if (rs->hist_entry >= 0) {
         pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),          pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
                 term_history[term_hist_entry]);                  rs->history[rs->hist_entry]);
         term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);          rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
     }      }
 }  }
   
 static void term_down_char(void)  static void readline_down_char(ReadLineState *rs)
 {  {
     if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)      if (rs->hist_entry == -1)
         return;          return;
     if (term_history[++term_hist_entry] != NULL) {      if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
         pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),          rs->history[++rs->hist_entry] != NULL) {
                 term_history[term_hist_entry]);          pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
                   rs->history[rs->hist_entry]);
     } else {      } else {
         term_hist_entry = -1;          rs->cmd_buf[0] = 0;
           rs->hist_entry = -1;
     }      }
     term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);      rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
 }  }
   
 static void term_hist_add(const char *cmdline)  static void readline_hist_add(ReadLineState *rs, const char *cmdline)
 {  {
     char *hist_entry, *new_entry;      char *hist_entry, *new_entry;
     int idx;      int idx;
Line 249  static void term_hist_add(const char *cm Line 217  static void term_hist_add(const char *cm
     if (cmdline[0] == '\0')      if (cmdline[0] == '\0')
         return;          return;
     new_entry = NULL;      new_entry = NULL;
     if (term_hist_entry != -1) {      if (rs->hist_entry != -1) {
         /* We were editing an existing history entry: replace it */          /* We were editing an existing history entry: replace it */
         hist_entry = term_history[term_hist_entry];          hist_entry = rs->history[rs->hist_entry];
         idx = term_hist_entry;          idx = rs->hist_entry;
         if (strcmp(hist_entry, cmdline) == 0) {          if (strcmp(hist_entry, cmdline) == 0) {
             goto same_entry;              goto same_entry;
         }          }
     }      }
     /* Search cmdline in history buffers */      /* Search cmdline in history buffers */
     for (idx = 0; idx < TERM_MAX_CMDS; idx++) {      for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
         hist_entry = term_history[idx];          hist_entry = rs->history[idx];
         if (hist_entry == NULL)          if (hist_entry == NULL)
             break;              break;
         if (strcmp(hist_entry, cmdline) == 0) {          if (strcmp(hist_entry, cmdline) == 0) {
         same_entry:          same_entry:
             new_entry = hist_entry;              new_entry = hist_entry;
             /* Put this entry at the end of history */              /* Put this entry at the end of history */
             memmove(&term_history[idx], &term_history[idx + 1],              memmove(&rs->history[idx], &rs->history[idx + 1],
                     (TERM_MAX_CMDS - idx + 1) * sizeof(char *));                      (READLINE_MAX_CMDS - idx + 1) * sizeof(char *));
             term_history[TERM_MAX_CMDS - 1] = NULL;              rs->history[READLINE_MAX_CMDS - 1] = NULL;
             for (; idx < TERM_MAX_CMDS; idx++) {              for (; idx < READLINE_MAX_CMDS; idx++) {
                 if (term_history[idx] == NULL)                  if (rs->history[idx] == NULL)
                     break;                      break;
             }              }
             break;              break;
         }          }
     }      }
     if (idx == TERM_MAX_CMDS) {      if (idx == READLINE_MAX_CMDS) {
         /* Need to get one free slot */          /* Need to get one free slot */
         free(term_history[0]);          free(rs->history[0]);
         memcpy(term_history, &term_history[1],          memcpy(rs->history, &rs->history[1],
                (TERM_MAX_CMDS - 1) * sizeof(char *));                 (READLINE_MAX_CMDS - 1) * sizeof(char *));
         term_history[TERM_MAX_CMDS - 1] = NULL;          rs->history[READLINE_MAX_CMDS - 1] = NULL;
         idx = TERM_MAX_CMDS - 1;          idx = READLINE_MAX_CMDS - 1;
     }      }
     if (new_entry == NULL)      if (new_entry == NULL)
         new_entry = strdup(cmdline);          new_entry = strdup(cmdline);
     term_history[idx] = new_entry;      rs->history[idx] = new_entry;
     term_hist_entry = -1;      rs->hist_entry = -1;
 }  }
   
 /* completion support */  /* completion support */
   
 void add_completion(const char *str)  void readline_add_completion(ReadLineState *rs, const char *str)
 {  {
     if (nb_completions < NB_COMPLETIONS_MAX) {      if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
         completions[nb_completions++] = qemu_strdup(str);          rs->completions[rs->nb_completions++] = qemu_strdup(str);
     }      }
 }  }
   
 static void term_completion(void)  void readline_set_completion_index(ReadLineState *rs, int index)
 {  {
       rs->completion_index = index;
   }
   
   static void readline_completion(ReadLineState *rs)
   {
       Monitor *mon = cur_mon;
     int len, i, j, max_width, nb_cols, max_prefix;      int len, i, j, max_width, nb_cols, max_prefix;
     char *cmdline;      char *cmdline;
   
     nb_completions = 0;      rs->nb_completions = 0;
   
     cmdline = qemu_malloc(term_cmd_buf_index + 1);      cmdline = qemu_malloc(rs->cmd_buf_index + 1);
     memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);      memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
     cmdline[term_cmd_buf_index] = '\0';      cmdline[rs->cmd_buf_index] = '\0';
     readline_find_completion(cmdline);      rs->completion_finder(cmdline);
     qemu_free(cmdline);      qemu_free(cmdline);
   
     /* no completion found */      /* no completion found */
     if (nb_completions <= 0)      if (rs->nb_completions <= 0)
         return;          return;
     if (nb_completions == 1) {      if (rs->nb_completions == 1) {
         len = strlen(completions[0]);          len = strlen(rs->completions[0]);
         for(i = completion_index; i < len; i++) {          for(i = rs->completion_index; i < len; i++) {
             term_insert_char(completions[0][i]);              readline_insert_char(rs, rs->completions[0][i]);
         }          }
         /* extra space for next argument. XXX: make it more generic */          /* extra space for next argument. XXX: make it more generic */
         if (len > 0 && completions[0][len - 1] != '/')          if (len > 0 && rs->completions[0][len - 1] != '/')
             term_insert_char(' ');              readline_insert_char(rs, ' ');
     } else {      } else {
         term_printf("\n");          monitor_printf(mon, "\n");
         max_width = 0;          max_width = 0;
         max_prefix = 0;           max_prefix = 0; 
         for(i = 0; i < nb_completions; i++) {          for(i = 0; i < rs->nb_completions; i++) {
             len = strlen(completions[i]);              len = strlen(rs->completions[i]);
             if (i==0) {              if (i==0) {
                 max_prefix = len;                  max_prefix = len;
             } else {              } else {
                 if (len < max_prefix)                  if (len < max_prefix)
                     max_prefix = len;                      max_prefix = len;
                 for(j=0; j<max_prefix; j++) {                  for(j=0; j<max_prefix; j++) {
                     if (completions[i][j] != completions[0][j])                      if (rs->completions[i][j] != rs->completions[0][j])
                         max_prefix = j;                          max_prefix = j;
                 }                  }
             }              }
Line 343  static void term_completion(void) Line 317  static void term_completion(void)
                 max_width = len;                  max_width = len;
         }          }
         if (max_prefix > 0)           if (max_prefix > 0) 
             for(i = completion_index; i < max_prefix; i++) {              for(i = rs->completion_index; i < max_prefix; i++) {
                 term_insert_char(completions[0][i]);                  readline_insert_char(rs, rs->completions[0][i]);
             }              }
         max_width += 2;          max_width += 2;
         if (max_width < 10)          if (max_width < 10)
Line 353  static void term_completion(void) Line 327  static void term_completion(void)
             max_width = 80;              max_width = 80;
         nb_cols = 80 / max_width;          nb_cols = 80 / max_width;
         j = 0;          j = 0;
         for(i = 0; i < nb_completions; i++) {          for(i = 0; i < rs->nb_completions; i++) {
             term_printf("%-*s", max_width, completions[i]);              monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);
             if (++j == nb_cols || i == (nb_completions - 1)) {              if (++j == nb_cols || i == (rs->nb_completions - 1)) {
                 term_printf("\n");                  monitor_printf(rs->mon, "\n");
                 j = 0;                  j = 0;
             }              }
         }          }
         term_show_prompt2();          readline_show_prompt(rs);
     }      }
 }  }
   
 /* return true if command handled */  /* return true if command handled */
 void readline_handle_byte(int ch)  void readline_handle_byte(ReadLineState *rs, int ch)
 {  {
     switch(term_esc_state) {      switch(rs->esc_state) {
     case IS_NORM:      case IS_NORM:
         switch(ch) {          switch(ch) {
         case 1:          case 1:
             term_bol();              readline_bol(rs);
             break;              break;
         case 4:          case 4:
             term_delete_char();              readline_delete_char(rs);
             break;              break;
         case 5:          case 5:
             term_eol();              readline_eol(rs);
             break;              break;
         case 9:          case 9:
             term_completion();              readline_completion(rs);
             break;              break;
         case 10:          case 10:
         case 13:          case 13:
             term_cmd_buf[term_cmd_buf_size] = '\0';              rs->cmd_buf[rs->cmd_buf_size] = '\0';
             if (!term_is_password)              if (!rs->read_password)
                 term_hist_add(term_cmd_buf);                  readline_hist_add(rs, rs->cmd_buf);
             term_printf("\n");              monitor_printf(rs->mon, "\n");
             term_cmd_buf_index = 0;              rs->cmd_buf_index = 0;
             term_cmd_buf_size = 0;              rs->cmd_buf_size = 0;
             term_last_cmd_buf_index = 0;              rs->last_cmd_buf_index = 0;
             term_last_cmd_buf_size = 0;              rs->last_cmd_buf_size = 0;
             /* NOTE: readline_start can be called here */              rs->readline_func(rs->mon, rs->cmd_buf, rs->readline_opaque);
             term_readline_func(term_readline_opaque, term_cmd_buf);  
             break;              break;
         case 23:          case 23:
             /* ^W */              /* ^W */
             term_backword();              readline_backword(rs);
             break;              break;
         case 27:          case 27:
             term_esc_state = IS_ESC;              rs->esc_state = IS_ESC;
             break;              break;
         case 127:          case 127:
         case 8:          case 8:
             term_backspace();              readline_backspace(rs);
             break;              break;
         case 155:          case 155:
             term_esc_state = IS_CSI;              rs->esc_state = IS_CSI;
             break;              break;
         default:          default:
             if (ch >= 32) {              if (ch >= 32) {
                 term_insert_char(ch);                  readline_insert_char(rs, ch);
             }              }
             break;              break;
         }          }
         break;          break;
     case IS_ESC:      case IS_ESC:
         if (ch == '[') {          if (ch == '[') {
             term_esc_state = IS_CSI;              rs->esc_state = IS_CSI;
             term_esc_param = 0;              rs->esc_param = 0;
         } else {          } else {
             term_esc_state = IS_NORM;              rs->esc_state = IS_NORM;
         }          }
         break;          break;
     case IS_CSI:      case IS_CSI:
         switch(ch) {          switch(ch) {
         case 'A':          case 'A':
         case 'F':          case 'F':
             term_up_char();              readline_up_char(rs);
             break;              break;
         case 'B':          case 'B':
         case 'E':          case 'E':
             term_down_char();              readline_down_char(rs);
             break;              break;
         case 'D':          case 'D':
             term_backward_char();              readline_backward_char(rs);
             break;              break;
         case 'C':          case 'C':
             term_forward_char();              readline_forward_char(rs);
             break;              break;
         case '0' ... '9':          case '0' ... '9':
             term_esc_param = term_esc_param * 10 + (ch - '0');              rs->esc_param = rs->esc_param * 10 + (ch - '0');
             goto the_end;              goto the_end;
         case '~':          case '~':
             switch(term_esc_param) {              switch(rs->esc_param) {
             case 1:              case 1:
                 term_bol();                  readline_bol(rs);
                 break;                  break;
             case 3:              case 3:
                 term_delete_char();                  readline_delete_char(rs);
                 break;                  break;
             case 4:              case 4:
                 term_eol();                  readline_eol(rs);
                 break;                  break;
             }              }
             break;              break;
         default:          default:
             break;              break;
         }          }
         term_esc_state = IS_NORM;          rs->esc_state = IS_NORM;
     the_end:      the_end:
         break;          break;
     }      }
     term_update();      readline_update(rs);
 }  }
   
 void readline_start(const char *prompt, int is_password,  void readline_start(ReadLineState *rs, const char *prompt, int read_password,
                     ReadLineFunc *readline_func, void *opaque)                      ReadLineFunc *readline_func, void *opaque)
 {  {
     pstrcpy(term_prompt, sizeof(term_prompt), prompt);      pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
     term_readline_func = readline_func;      rs->readline_func = readline_func;
     term_readline_opaque = opaque;      rs->readline_opaque = opaque;
     term_is_password = is_password;      rs->read_password = read_password;
     term_show_prompt();      readline_restart(rs);
   }
   
   void readline_restart(ReadLineState *rs)
   {
       rs->cmd_buf_index = 0;
       rs->cmd_buf_size = 0;
 }  }
   
 const char *readline_get_history(unsigned int index)  const char *readline_get_history(ReadLineState *rs, unsigned int index)
 {  {
     if (index >= TERM_MAX_CMDS)      if (index >= READLINE_MAX_CMDS)
         return NULL;          return NULL;
     return term_history[index];      return rs->history[index];
   }
   
   ReadLineState *readline_init(Monitor *mon,
                                ReadLineCompletionFunc *completion_finder)
   {
       ReadLineState *rs = qemu_mallocz(sizeof(*rs));
   
       rs->hist_entry = -1;
       rs->mon = mon;
       rs->completion_finder = completion_finder;
   
       return rs;
 }  }

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


unix.superglobalmegacorp.com