From nobody Sun Feb 8 15:42:08 2026 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 1510057392053140.92761683998833; Tue, 7 Nov 2017 04:23:12 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 673B33DE31; Tue, 7 Nov 2017 12:23:08 +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 3FE7D6A023; Tue, 7 Nov 2017 12:23:08 +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 951474BB79; Tue, 7 Nov 2017 12:23:07 +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 vA7CN5nY031600 for ; Tue, 7 Nov 2017 07:23:05 -0500 Received: by smtp.corp.redhat.com (Postfix) id D99FA5C545; Tue, 7 Nov 2017 12:23:05 +0000 (UTC) Received: from moe.brq.redhat.com (unknown [10.43.2.192]) by smtp.corp.redhat.com (Postfix) with ESMTP id 609EC1821D for ; Tue, 7 Nov 2017 12:23:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 673B33DE31 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=libvir-list-bounces@redhat.com From: Michal Privoznik To: libvir-list@redhat.com Date: Tue, 7 Nov 2017 13:22:49 +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 01/11] vshCommandStringParse: Allow retrieving partial result 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.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 07 Nov 2017 12:23:09 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" In the future, this function is going to be called from vshReadlineParse() to provide parsed input for completer callbacks. The idea is to allow the callbacks to provide more specific data. For instance, for the following input: virsh # domifaddr --domain fedora --interface the --interface completer callback is going to be called. Now, it is more user friendly if the completer offers only those interfaces found in 'fedora' domain. But in order to do that it needs to be able to retrieve partially parsed result. Signed-off-by: Michal Privoznik --- tools/virsh.c | 4 ++-- tools/virt-admin.c | 4 ++-- tools/vsh.c | 67 ++++++++++++++++++++++++++++++++++----------------= ---- tools/vsh.h | 2 +- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index d1789f03a..d0c135016 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -815,7 +815,7 @@ virshParseArgv(vshControl *ctl, int argc, char **argv) ctl->imode =3D false; if (argc - optind =3D=3D 1) { vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]= ); - return vshCommandStringParse(ctl, argv[optind]); + return vshCommandStringParse(ctl, argv[optind], NULL); } else { return vshCommandArgvParse(ctl, argc - optind, argv + optind); } @@ -952,7 +952,7 @@ main(int argc, char **argv) #if WITH_READLINE add_history(ctl->cmdstr); #endif - if (vshCommandStringParse(ctl, ctl->cmdstr)) + if (vshCommandStringParse(ctl, ctl->cmdstr, NULL)) vshCommandRun(ctl, ctl->cmd); } VIR_FREE(ctl->cmdstr); diff --git a/tools/virt-admin.c b/tools/virt-admin.c index e529a2891..b8b33af19 100644 --- a/tools/virt-admin.c +++ b/tools/virt-admin.c @@ -1335,7 +1335,7 @@ vshAdmParseArgv(vshControl *ctl, int argc, char **arg= v) ctl->imode =3D false; if (argc - optind =3D=3D 1) { vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]= ); - return vshCommandStringParse(ctl, argv[optind]); + return vshCommandStringParse(ctl, argv[optind], NULL); } else { return vshCommandArgvParse(ctl, argc - optind, argv + optind); } @@ -1555,7 +1555,7 @@ main(int argc, char **argv) #if WITH_READLINE add_history(ctl->cmdstr); #endif - if (vshCommandStringParse(ctl, ctl->cmdstr)) + if (vshCommandStringParse(ctl, ctl->cmdstr, NULL)) vshCommandRun(ctl, ctl->cmd); } VIR_FREE(ctl->cmdstr); diff --git a/tools/vsh.c b/tools/vsh.c index 10a65c39f..eca312b4b 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1387,26 +1387,27 @@ struct _vshCommandParser { }; =20 static bool -vshCommandParse(vshControl *ctl, vshCommandParser *parser) +vshCommandParse(vshControl *ctl, vshCommandParser *parser, vshCmd **partia= l) { char *tkdata =3D NULL; vshCmd *clast =3D NULL; vshCmdOpt *first =3D NULL; + const vshCmdDef *cmd =3D NULL; =20 - if (ctl->cmd) { + if (!partial && ctl->cmd) { vshCommandFree(ctl->cmd); ctl->cmd =3D NULL; } =20 while (1) { vshCmdOpt *last =3D NULL; - const vshCmdDef *cmd =3D NULL; vshCommandToken tk; bool data_only =3D false; uint64_t opts_need_arg =3D 0; uint64_t opts_required =3D 0; uint64_t opts_seen =3D 0; =20 + cmd =3D NULL; first =3D NULL; =20 while (1) { @@ -1425,7 +1426,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser) if (cmd =3D=3D NULL) { /* first token must be command name */ if (!(cmd =3D vshCmddefSearch(tkdata))) { - vshError(ctl, _("unknown command: '%s'"), tkdata); + if (!partial) + vshError(ctl, _("unknown command: '%s'"), tkdata); goto syntaxError; /* ... or ignore this command only= ? */ } =20 @@ -1437,9 +1439,10 @@ vshCommandParse(vshControl *ctl, vshCommandParser *p= arser) } if (vshCmddefOptParse(cmd, &opts_need_arg, &opts_required) < 0) { - vshError(ctl, - _("internal error: bad options in command: '%= s'"), - tkdata); + if (!partial) + vshError(ctl, + _("internal error: bad options in command= : '%s'"), + tkdata); goto syntaxError; } VIR_FREE(tkdata); @@ -1474,11 +1477,12 @@ vshCommandParse(vshControl *ctl, vshCommandParser *= parser) if (tk =3D=3D VSH_TK_ERROR) goto syntaxError; if (tk !=3D VSH_TK_ARG) { - vshError(ctl, - _("expected syntax: --%s <%s>"), - opt->name, - opt->type =3D=3D - VSH_OT_INT ? _("number") : _("string")); + if (!partial) + vshError(ctl, + _("expected syntax: --%s <%s>"), + opt->name, + opt->type =3D=3D + VSH_OT_INT ? _("number") : _("string"= )); goto syntaxError; } if (opt->type !=3D VSH_OT_ARGV) @@ -1486,8 +1490,9 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser) } else { tkdata =3D NULL; if (optstr) { - vshError(ctl, _("invalid '=3D' after option --%s"), - opt->name); + if (!partial) + vshError(ctl, _("invalid '=3D' after option --= %s"), + opt->name); VIR_FREE(optstr); goto syntaxError; } @@ -1502,7 +1507,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *pa= rser) if (!(opt =3D vshCmddefGetData(cmd, &opts_need_arg, &opts_seen)) && STRNEQ(cmd->name, "help")) { - vshError(ctl, _("unexpected data '%s'"), tkdata); + if (!partial) + vshError(ctl, _("unexpected data '%s'"), tkdata); goto syntaxError; } } @@ -1558,12 +1564,15 @@ vshCommandParse(vshControl *ctl, vshCommandParser *= parser) c->def =3D cmd; c->next =3D NULL; =20 - if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0)= { + if (!partial && + vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0)= { VIR_FREE(c); goto syntaxError; } =20 - if (!ctl->cmd) + if (partial) + *partial =3D c; + else if (!ctl->cmd) ctl->cmd =3D c; if (clast) clast->next =3D c; @@ -1577,12 +1586,20 @@ vshCommandParse(vshControl *ctl, vshCommandParser *= parser) return true; =20 syntaxError: - if (ctl->cmd) { - vshCommandFree(ctl->cmd); - ctl->cmd =3D NULL; + if (partial) { + if (!*partial) + *partial =3D vshMalloc(ctl, sizeof(vshCmd)); + + (*partial)->opts =3D first; + (*partial)->def =3D cmd; + } else { + if (ctl->cmd) { + vshCommandFree(ctl->cmd); + ctl->cmd =3D NULL; + } + if (first) + vshCommandOptFree(first); } - if (first) - vshCommandOptFree(first); VIR_FREE(tkdata); return false; } @@ -1617,7 +1634,7 @@ vshCommandArgvParse(vshControl *ctl, int nargs, char = **argv) parser.arg_pos =3D argv; parser.arg_end =3D argv + nargs; parser.getNextArg =3D vshCommandArgvGetArg; - return vshCommandParse(ctl, &parser); + return vshCommandParse(ctl, &parser, NULL); } =20 /* ---------------------- @@ -1689,7 +1706,7 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandPar= ser *parser, char **res, } =20 bool -vshCommandStringParse(vshControl *ctl, char *cmdstr) +vshCommandStringParse(vshControl *ctl, char *cmdstr, vshCmd **partial) { vshCommandParser parser; =20 @@ -1698,7 +1715,7 @@ vshCommandStringParse(vshControl *ctl, char *cmdstr) =20 parser.pos =3D cmdstr; parser.getNextArg =3D vshCommandStringGetArg; - return vshCommandParse(ctl, &parser); + return vshCommandParse(ctl, &parser, partial); } =20 /** diff --git a/tools/vsh.h b/tools/vsh.h index ab755bccf..8f7df9ff8 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -299,7 +299,7 @@ int vshBlockJobOptionBandwidth(vshControl *ctl, unsigned long *bandwidth); bool vshCommandOptBool(const vshCmd *cmd, const char *name); bool vshCommandRun(vshControl *ctl, const vshCmd *cmd); -bool vshCommandStringParse(vshControl *ctl, char *cmdstr); +bool vshCommandStringParse(vshControl *ctl, char *cmdstr, vshCmd **partial= ); =20 const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd, const vshCmdOpt *opt); --=20 2.13.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list