func: static void monitor_find_completion(const char *cmdline)
  
  {
  
      const char *cmdname;
  
      char *args[MAX_ARGS];
  
      int nb_args, i, len;
  
      const char *ptype, *str;
  
      const mon_cmd_t *cmd;
  
      const KeyDef *key;
  
  
  
      parse_cmdline(cmdline, &nb_args, args);
  
  #ifdef DEBUG_COMPLETION
  
      for(i = 0; i < nb_args; i++) {
  
          monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
  
      }
  
  #endif
  
  
  
      /* if the line ends with a space, it means we want to complete the
  
         next arg */
  
      len = strlen(cmdline);
  
      if (len > 0 && qemu_isspace(cmdline[len - 1])) {
  
          if (nb_args >= MAX_ARGS)
  
              return;
  
          args[nb_args++] = qemu_strdup("");
  
      }
  
      if (nb_args <= 1) {
  
          /* command completion */
  
          if (nb_args == 0)
  
              cmdname = "";
  
          else
  
              cmdname = args[0];
  
          readline_set_completion_index(cur_mon->rs, strlen(cmdname));
  
          for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
  
              cmd_completion(cmdname, cmd->name);
  
          }
  
      } else {
  
          /* find the command */
  
          for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
  
              if (compare_cmd(args[0], cmd->name))
  
                  goto found;
  
          }
  
          return;
  
      found:
  
          ptype = next_arg_type(cmd->args_type);
  
          for(i = 0; i < nb_args - 2; i++) {
  
              if (*ptype != '\0') {
  
                  ptype = next_arg_type(ptype);
  
                  while (*ptype == '?')
  
                      ptype = next_arg_type(ptype);
  
              }
  
          }
  
          str = args[nb_args - 1];
  
          if (*ptype == '-' && ptype[1] != '\0') {
  
              ptype += 2;
  
          }
  
          switch(*ptype) {
  
          case 'F':
  
              /* file completion */
  
              readline_set_completion_index(cur_mon->rs, strlen(str));
  
              file_completion(str);
  
              break;
  
          case 'B':
  
              /* block device name completion */
  
              readline_set_completion_index(cur_mon->rs, strlen(str));
  
              bdrv_iterate(block_completion_it, (void *)str);
  
              break;
  
          case 's':
  
              /* XXX: more generic ? */
  
              if (!strcmp(cmd->name, "info")) {
  
                  readline_set_completion_index(cur_mon->rs, strlen(str));
  
                  for(cmd = info_cmds; cmd->name != NULL; cmd++) {
  
                      cmd_completion(str, cmd->name);
  
                  }
  
              } else if (!strcmp(cmd->name, "sendkey")) {
  
                  char *sep = strrchr(str, '-');
  
                  if (sep)
  
                      str = sep + 1;
  
                  readline_set_completion_index(cur_mon->rs, strlen(str));
  
                  for(key = key_defs; key->name != NULL; key++) {
  
                      cmd_completion(str, key->name);
  
                  }
  
              } else if (!strcmp(cmd->name, "help|?")) {
  
                  readline_set_completion_index(cur_mon->rs, strlen(str));
  
                  for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
  
                      cmd_completion(str, cmd->name);
  
                  }
  
              }
  
              break;
  
          default:
  
              break;
  
          }
  
      }
  
      for(i = 0; i < nb_args; i++)
  
          qemu_free(args[i]);
  
  }
  