From nobody Thu May 15 07:08:41 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1514913154827482.0807889463765; Tue, 2 Jan 2018 09:12:34 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 865497EA84; Tue, 2 Jan 2018 17:12:33 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 62CE160C99; Tue, 2 Jan 2018 17:12:33 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 298E23FCFB; Tue, 2 Jan 2018 17:12:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w02HCVoW003099 for ; Tue, 2 Jan 2018 12:12:31 -0500 Received: by smtp.corp.redhat.com (Postfix) id 97F9E5C3F8; Tue, 2 Jan 2018 17:12:31 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-45.brq.redhat.com [10.40.204.45]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0BF7E5C890 for ; Tue, 2 Jan 2018 17:12:26 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Tue, 2 Jan 2018 18:11:58 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 05/18] vshReadlineParse: Drop code duplication X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 02 Jan 2018 17:12:33 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Now that we have a way of retrieving partly parsed command we don't need duplicate code that parses the user's input. Yes, this code removes call of opt's completer, but: a) current implementation is broken anyway, and b) it will be added back shortly Signed-off-by: Michal Privoznik --- tools/vsh.c | 214 +++++++-------------------------------------------------= ---- 1 file changed, 24 insertions(+), 190 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index 34eb592ef..c3423d6e3 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -2697,216 +2697,50 @@ vshReadlineOptionsGenerator(const char *text, int = state, const vshCmdDef *cmd_pa static char * vshReadlineParse(const char *text, int state) { - static vshCommandParser parser, sanitizer; - vshCommandToken tk; + static vshCmd *partial; static const vshCmdDef *cmd; - const vshCmdOptDef *opt =3D NULL; - char *tkdata, *optstr, *const_tkdata, *completed_name; char *res =3D NULL; - static char *ctext, *sanitized_text; - static char **completed_list; - static unsigned int completed_list_index; - static uint64_t const_opts_need_arg, const_opts_required, const_opts_s= een; - uint64_t opts_seen; - size_t opt_index; - static bool cmd_exists, opts_filled, opt_exists; - static bool non_bool_opt_exists, data_complete; =20 if (!state) { - parser.pos =3D rl_line_buffer; - parser.getNextArg =3D vshCommandStringGetArg; - - ctext =3D vshStrdup(NULL, text); - sanitizer.pos =3D ctext; - sanitizer.getNextArg =3D vshCommandStringGetArg; - - const_tkdata =3D NULL; - tkdata =3D NULL; - sanitized_text =3D NULL; - optstr =3D NULL; - - completed_list =3D NULL; - completed_list_index =3D 0; - - /* Sanitize/de-quote the autocomplete text */ - tk =3D sanitizer.getNextArg(NULL, &sanitizer, &sanitized_text, fal= se); - - /* No autocomplete if sanitized text is a token error or token end= */ - if (tk =3D=3D VSH_TK_ERROR) - goto error; - - tk =3D parser.getNextArg(NULL, &parser, &const_tkdata, false); - - if (tk =3D=3D VSH_TK_ERROR) - goto error; - - /* Free-ing purposes */ - tkdata =3D const_tkdata; - /* Skip leading space */ - virSkipSpaces((const char**)&tkdata); - - /* Handle ';'s */ - while (tk =3D=3D VSH_TK_SUBCMD_END) { - tk =3D parser.getNextArg(NULL, &parser, &const_tkdata, false); - tkdata =3D const_tkdata; - } - - /* Skip trailing space after ;*/ - virSkipSpaces((const char**)&tkdata); - - cmd_exists =3D false; - opts_filled =3D false; - non_bool_opt_exists =3D false; - data_complete =3D false; - - const_opts_need_arg =3D 0; - const_opts_required =3D 0; - const_opts_seen =3D 0; - - opt_index =3D 0; + char *buf =3D vshStrdup(NULL, rl_line_buffer); =20 + vshCommandFree(partial); + partial =3D NULL; cmd =3D NULL; - opt =3D NULL; =20 - /* Parse till text to be auto-completed is reached */ - while (STRNEQ(tkdata, sanitized_text)) { - if (!cmd) { - if (!(cmd =3D vshCmddefSearch(tkdata))) - goto error; - if (cmd->flags & VSH_CMD_FLAG_ALIAS) - cmd =3D vshCmddefSearch(cmd->alias); + *(buf + rl_point) =3D '\0'; =20 - cmd_exists =3D true; - if (vshCmddefOptParse(cmd, &const_opts_need_arg, - &const_opts_required) < 0) - goto error; - opts_seen =3D const_opts_seen; - opts_filled =3D true; - } else if (tkdata[0] =3D=3D '-' && tkdata[1] =3D=3D '-' && - c_isalnum(tkdata[2])) { - /* Command retrieved successfully, move to options */ - optstr =3D strchr(tkdata + 2, '=3D'); - opt_index =3D 0; + vshCommandStringParse(NULL, buf, &partial); =20 - if (optstr) { - *optstr =3D '\0'; - optstr =3D vshStrdup(NULL, optstr + 1); - } + VIR_FREE(buf); =20 - if (!(opt =3D vshCmddefGetOption(NULL, cmd, tkdata + 2, - &opts_seen, &opt_index, - &optstr, false))) { - /* Parsing failed wrt autocomplete */ - VIR_FREE(optstr); - goto error; - } + if (partial) + cmd =3D partial->def; =20 - opts_seen =3D const_opts_seen; - opt_exists =3D true; - VIR_FREE(const_tkdata); - if (opt->type !=3D VSH_OT_BOOL) { - non_bool_opt_exists =3D true; - /* Opt exists and check for option data */ - if (optstr) { - const_tkdata =3D optstr; - tkdata =3D const_tkdata; - } else { - VIR_FREE(const_tkdata); - tk =3D parser.getNextArg(NULL, &parser, &const_tkd= ata, - false); - - if (tk =3D=3D VSH_TK_ERROR) - goto error; - - tkdata =3D const_tkdata; - virSkipSpaces((const char **)&tkdata); - } - if (STREQ(tkdata, sanitized_text)) { - /* auto-complete non-bool option arg */ - data_complete =3D true; - break; - } - non_bool_opt_exists =3D false; - } else { - tkdata =3D NULL; - /* opt type is BOOL */ - if (optstr) { - VIR_FREE(optstr); - goto error; - } - } - } else if (!opt_exists) { - /* No -- option provided and some other token given - * Try to find the default option. - */ - if (!(opt =3D vshCmddefGetData(cmd, &const_opts_need_arg, - &const_opts_seen)) - || opt->type =3D=3D VSH_OT_BOOL) - goto error; - opt_exists =3D true; - opts_seen =3D const_opts_seen; - } else { - /* In every other case, return NULL */ - goto error; - } - - VIR_FREE(const_tkdata); - tk =3D parser.getNextArg(NULL, &parser, &const_tkdata, false); - - if (tk =3D=3D VSH_TK_ERROR) - goto error; - - while (tk =3D=3D VSH_TK_SUBCMD_END) { - cmd =3D NULL; - cmd_exists =3D false; - opts_filled =3D false; - opt =3D NULL; - non_bool_opt_exists =3D false; - tk =3D parser.getNextArg(NULL, &parser, &const_tkdata, fal= se); - } - - tkdata =3D const_tkdata; - - virSkipSpaces((const char**)&tkdata); + if (cmd && STREQ(cmd->name, text)) { + /* Corner case - some commands share prefix (e.g. + * dump and dumpxml). If user typed 'dump', + * then @text =3D "dump" and we want to offer command + * completion. If they typed 'dump ' then + * @text =3D "" (the space after the command) and we + * want to offer options completion for dump command. + */ + cmd =3D NULL; } - VIR_FREE(const_tkdata); } =20 - if (!cmd_exists) { - res =3D vshReadlineCommandGenerator(sanitized_text, state); - } else if (opts_filled && !non_bool_opt_exists) { - res =3D vshReadlineOptionsGenerator(sanitized_text, state, cmd); - } else if (non_bool_opt_exists && data_complete && opt && opt->complet= er) { - if (!completed_list) - completed_list =3D opt->completer(autoCompleteOpaque, - opt->completer_flags); - if (completed_list) { - while ((completed_name =3D completed_list[completed_list_index= ])) { - completed_list_index++; - if (!STRPREFIX(completed_name, sanitized_text)) - continue; - res =3D vshStrdup(NULL, completed_name); - return res; - } - res =3D NULL; - virStringListFree(completed_list); - completed_list_index =3D 0; - } + if (!cmd) { + res =3D vshReadlineCommandGenerator(text, state); + } else { + res =3D vshReadlineOptionsGenerator(text, state, cmd); } =20 if (!res) { - VIR_FREE(sanitized_text); - VIR_FREE(ctext); + vshCommandFree(partial); + partial =3D NULL; } =20 return res; - - error: - VIR_FREE(const_tkdata); - VIR_FREE(sanitized_text); - VIR_FREE(ctext); - return NULL; - } =20 static char ** --=20 2.13.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list