From patchwork Sun Mar 3 12:19:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579740 Received: from mout.web.de (mout.web.de [212.227.15.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B12FC2FE for ; Sun, 3 Mar 2024 12:20:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468404; cv=none; b=TiEMZ+fCQv/LzlRA/B+j25BsUQlfn1TQDxqX+v8/PDN9gxM6A9vlUiZs9ozZsYWGypZPAPdYwLDES9W1gl/lPezAAQdrx/X/SGB+1n72U3KHGt3vpzXQ+3vFvs3RrcOrz2wWOTFW7u46YdCOW8ZrGr7FTTFhK0nikROZIKTu+/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468404; c=relaxed/simple; bh=DWXSv1Oj582R4Wze3wpH416l7a/s8OuE9sb06gmmfaY=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zte+lEtMrLjTIeZCVZCGJMiY+io/duz+YiWOnT1Qz1fzaA0adnEYmNzo9kLisW9RbraC7HaVPaHkqGc9Rrl0tLYigwrCj5YHHUfEh+I1hGQfRs3s5Y0W2JyFSqAsQtLXx8+Y/U8PL/w9DyY92I5KDYuUG3pFmD8RcskVVELFPeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=cinh0ZI8; arc=none smtp.client-ip=212.227.15.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="cinh0ZI8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468393; x=1710073193; i=l.s.r@web.de; bh=DWXSv1Oj582R4Wze3wpH416l7a/s8OuE9sb06gmmfaY=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=cinh0ZI8btqW9y75Wr2jEMkLoBRKOQsYM/osftJzmJp9ib7nGOIgi1XVqlIc0MoL IJl9UFvXvfPgrXZm5rLogYk6tIFYGi3xR3wJWkJZ+yEUEaWC+5FYvlsc5SZlIRfUN m92IpDHnxoASlHQdGtiLc1/A99RRMbh/ywC6vXjzDOZPZEWce/dfdTpMuBVi9ssxe q6uUGgQVAvPxY4M9/tOruXfvS8Ydv5JrxaqPlTotVoIea05dF7DM5HZngSgt2fbd3 pQ/IfjpA0ynoEBhvFm0wYdv0Aud93+linNYs8lQ8oSB+naUnmcNlyAU4UEd/gF4Nq ACrtYvv/WxURK6zKdw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MLRYd-1rPuUU1Nat-00Ib1B for ; Sun, 03 Mar 2024 13:19:53 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 1/6] parse-options: recognize abbreviated negated option with arg Date: Sun, 3 Mar 2024 13:19:38 +0100 Message-ID: <20240303121944.20627-2-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:+FBaFes9b0SMA0fva+3H4nWvLv93R6+DpqcTEnYa8dkzTqXJ8CO X0a4ovcIGMtF+1vz9kAD4FcdB9fRB2XcliEfDBizz94ypM9+vS/vx6C01uIL5mqbKtKDbFF RHaM1e8f5gWT59YnWNEZdG6aLEqdYPVTfiszDCYTen8O3C0Lb0WJuHSPddwfytuH9Mj3url HLvvQdO5XNiW2bsPOmkVA== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:IBjmkPtIcnA=;EwRl8nIh06vGLJvvDeH91MdDK6d U/p0+30wlhxzzxgUHgpsUDNUEtVcWkJOpxki/e4NT6+5MCvjbEilnFPTw5yQfmtrlR6xCMW9W j7C0TYTXWBOp82eZ8WIsT8byKuw8hxRCjbEIM+HRCPKSzQNPaWjfgpCAyFH9YJuCw/gqDQCET gKpNIru2TUTdtcB6G6usIl+95etnnaeXWxuyGdlf/1j9DGYYY6D69G32QKt0M46GMq/ZqHacn 1coU7/9CJZ0xuethOTt7hjaSadCCtByQO1ayM7jv0f2decNzg0CUNdMRfvH04ZsWkHZXB6WsQ g5b0u/oA5wUWS6iPK+6FDY8Qq3Qni2WXFQIQ2pTWeZploqiEQJT1kTuj9FdoY1cAavvNeswys /41pHLlHlkdJJ79FLqAJ1HNNqse+KpBFK1lvwX4JlWkQZqfkc3U0uyn0PkFM6vqRAVSMBzrcl LGOu9BBzDwhpBANAlw6x29xlZi+bFWDOlfbWJYOZyokKCLcbDbkGzEmb1d+SpgP4oszvhnDmR DNKO3fTI8/6GcPx+L1j0/iym0/x7jlk+0R1mVq7rJ3PdEiPQwUU3Rj/fJ319I5bGv+txPg/Pv uUGtDh0J3yyXyRFawShDW9hf2nRdgQZOvCCX5yxkDERDq/C2hTPVIS3AJmg6HDTgKgmuZ2jjg bIW+ouCYwQcB59iXgs1HEjT+dYFOMWj4xc5/GrAInJc6ojhRl1b2Na+ROcq9karaDxhWlzh0x bw2yW4s144cF0MJrSwb7pIFLHgD3WhVx6QcnH0Xsdsx7/HqVkUTaiTVExH7LybS2Wl0gyodWX PwcyIxvAgfLv+aqI0PGoRDAeG8Xblo8QM1JNNQ62Mid5o= Giving an argument to an option that doesn't take one causes Git to report that error specifically: $ git rm --dry-run=bogus error: option `dry-run' takes no value The same is true when the option is negated or abbreviated: $ git rm --no-dry-run=bogus error: option `no-dry-run' takes no value $ git rm --dry=bogus error: option `dry-run' takes no value Not so when doing both, though: $ git rm --no-dry=bogus error: unknown option `no-dry=bogus' usage: git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] (Rest of the usage message omitted.) Improve consistency and usefulness of the error message by recognizing abbreviated negated options even if they have a (most likely bogus) argument. With this patch we get: $ git rm --no-dry=bogus error: option `no-dry-run' takes no value Signed-off-by: René Scharfe --- parse-options.c | 5 +++-- t/t0040-parse-options.sh | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index 63a99dea6e..e4ce33ea48 100644 --- a/parse-options.c +++ b/parse-options.c @@ -391,7 +391,7 @@ static enum parse_opt_result parse_long_opt( ambiguous_option = abbrev_option; ambiguous_flags = abbrev_flags; } - if (!(flags & OPT_UNSET) && *arg_end) + if (*arg_end) p->opt = arg_end + 1; abbrev_option = options; abbrev_flags = flags ^ opt_flags; @@ -412,7 +412,8 @@ static enum parse_opt_result parse_long_opt( if (!skip_prefix(arg + 3, long_name, &rest)) { /* abbreviated and negated? */ if (allow_abbrev && - starts_with(long_name, arg + 3)) + !strncmp(long_name, arg + 3, + arg_end - arg - 3)) goto is_abbreviated; else continue; diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ec974867e4..8bb2a8b453 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -210,6 +210,22 @@ test_expect_success 'superfluous value provided: boolean' ' test_cmp expect actual ' +test_expect_success 'superfluous value provided: boolean, abbreviated' ' + cat >expect <<-\EOF && + error: option `yes'\'' takes no value + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --ye=hi 2>actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + error: option `no-yes'\'' takes no value + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --no-ye=hi 2>actual && + test_cmp expect actual +' + test_expect_success 'superfluous value provided: cmdmode' ' cat >expect <<-\EOF && error: option `mode1'\'' takes no value From patchwork Sun Mar 3 12:19:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579738 Received: from mout.web.de (mout.web.de [212.227.15.14]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECA00C13D for ; Sun, 3 Mar 2024 12:19:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468401; cv=none; b=Kai3zR+YZ7w+zVCvXpUKblKVGCU9Xp9t9prUCvtbBqeiMDreLK3pe5bRHf+Zon+GnODMPxz2smSlC1wPzq2fng9ThayDla2xJVIfwVgclZERXVAt9b7LCoBfoXJW2BfhwznZ6xhfNt81VMRuneO0McKjtU6wQdaZlr3eRSaSm4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468401; c=relaxed/simple; bh=SXKOH9kzxlmw7arRinl11yNleQFuBmLCTCOP3/PU0lQ=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=r/EbO/g6V9C9JunQ7s2gNJgVLWmnOcyl3SkjRRolRU19ghskOwNUdz+9sRr+5wSRo/BwhSE4b26uR2AssyQHhD7SmSzKYIlxKum1Zw+uc96xHGzRlN6HxDxhUmOdd9PvGX21WTeqbB3d7qp9s8vtbVY9b5OkQu99x0ldUSP+hNc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=GKaWJ2vE; arc=none smtp.client-ip=212.227.15.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="GKaWJ2vE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468393; x=1710073193; i=l.s.r@web.de; bh=SXKOH9kzxlmw7arRinl11yNleQFuBmLCTCOP3/PU0lQ=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=GKaWJ2vE1wWfzDkmCzJlq3is68z+bmdlaV1NfQ5oHGGIVFtoowGi4OtkDaJeB/Po cxBNzs39OD+dXZZyl6CzMP5hL/rDMGZgox1Zlz+bpZTO1mmKfEpbsz4L3Znla+zAj UdPlJrfhmFj1NIprS+zlwizKF1+TPXfTf4/HAU96vt6upU/ZakIjjClhfrXG7Fe3+ UQvnfxYIFyL6masmWTwKdSIWPOqDyBN6AEHDpcBToVq98kF9EEaIsVZqYM/E3NGwS 7LRhnnYWK1CbzmD0Ny0lmUW23NP6Ouyhb1I7WNeLspMhlQdmfRMEf2EJrwjJwD62T ocDX6KAQ3tIx6Wew4w== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MrOhn-1r30Lm1vzL-00oPer for ; Sun, 03 Mar 2024 13:19:53 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 2/6] parse-options: set arg of abbreviated option lazily Date: Sun, 3 Mar 2024 13:19:39 +0100 Message-ID: <20240303121944.20627-3-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:uM+V6pGPt+VgygEjLkspfSQUZczj3ZMF6BUSv/DwxSTkndVGXhF bSgSNd8R0p8Z7mRzkEzUeZucdrrhw49CG+ASN8kdQPBaHCXio9CKCPwvQ7cx1hySYumzWPt YxyAzRLnWi0Azokpvp2e3CFtIJLbKiyNEnR6ahZ1ZjrMyf9wTYlvgpZNrgOX4cCCR1TctZI 9r6Fi1iGPwmGJHvuP/K6w== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:r6w7WAuTd9k=;WhoW4O0LbwesaQwLy5mpGbaBIim Usr4tCH8wpPILNshP/PqjNpls7NL0sll7Vtt6SNN7RFV3uES5vLBzr04nT+IlLxiaFmO6Xrh5 Qt0Y1i3yZTxjvKUgBrwPRL8AcxK2YlU0QICRqPu2e233iVLba8PwvI4KaXFHkw0lldpHvoDq/ jC9o5kK7HxgW3YxhhyUb0LdS6go12CQZZH1JZLfpLDuHNqm3VucJOuHes2VOnCoAFx8uQUtC3 zcpBn+VgmEiEFfHfE2nKK/P2BSZ2jDB+j4ITSJCCjYZj9plh/5rTM7/LjEKbjrKs5wlZb2Iah bcOlTP+SF01gp2bRRt/XvToDUIO7lKFMiC9hEITKqqO05KLuO/C5bTY0R067HCpcpeVyIsA26 Db9p9F3nLZo4JFupLKDPUvFrUMDefHrQgefwzAgrDv6yqReT6LWuP7ZoaeDBRVB86VyIuQCe/ r1OxcUBNXH3Fi9eSGt+3Id0z6ruwDH2Q+YVcdE5cLAoFlbh5hTRVqBFWPF4ODiFuTchh5icYF /vPAL6uT8oFGgKPHMc4bwVyHW1AFw/eDs4x4H67Cm3BECql1PweeqFrjUwiCT64B4raHobzpB K297sZtSR9gD0FYx9IVPTrocugZpiI2F68VZB+h5FLZCuIyjzQHuCbWHJbMzy3vAKPIzX9OIT Ep1R6Y2McQEbm5X72vFIxpwJv/9E4EhRx/xNZXcyhfhJnsZ3WBQ9BGC37SjB5hWiinfex9O2/ oC/J+F+BY8uutVLvB7ENR4gTpa4PE1v9CtaCaHYd+UPmZarRFiowB75qj2rOBAwth+RawUHwz ZyhzxVTA487Eg+2N4h5toPelAmLvn1HdNAg6uS2NjhNSk= Postpone setting the opt pointer until we're about to call get_value(), which uses it. There's no point in setting it eagerly for every abbreviated candidate option, which may turn out to be ambiguous. Removing this assignment from the loop doesn't noticeably improve the performance, but allows further simplification. Signed-off-by: René Scharfe --- parse-options.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index e4ce33ea48..056c6b30e9 100644 --- a/parse-options.c +++ b/parse-options.c @@ -391,8 +391,6 @@ static enum parse_opt_result parse_long_opt( ambiguous_option = abbrev_option; ambiguous_flags = abbrev_flags; } - if (*arg_end) - p->opt = arg_end + 1; abbrev_option = options; abbrev_flags = flags ^ opt_flags; continue; @@ -441,8 +439,11 @@ static enum parse_opt_result parse_long_opt( abbrev_option->long_name); return PARSE_OPT_HELP; } - if (abbrev_option) + if (abbrev_option) { + if (*arg_end) + p->opt = arg_end + 1; return get_value(p, abbrev_option, abbrev_flags); + } return PARSE_OPT_UNKNOWN; } From patchwork Sun Mar 3 12:19:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579743 Received: from mout.web.de (mout.web.de [212.227.15.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A094BD2FF for ; Sun, 3 Mar 2024 12:20:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468405; cv=none; b=R1UD2AF0b50jl2e0Sp+RQ/ONeQDDC4CYxztJ+qyqtK8vALru/uj0OY+svhXJZ87GuXMBrWyhmGMTioHNkUK6Z8uDs7dzCH353UH23KqNhLJDxZPoqLwJ4Hsc3FpTV3A94cd9E8MAwPpUn0lrGV59eiPDzxFWMcFjtGkkTVWBOIU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468405; c=relaxed/simple; bh=TMiHPegQUo5WD5H3L2SdR8bYUsLkTA/0O79Y1122BU8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OGuczNGD9RhGnIkJuoSdFyFRp0+ScUIqGxxDuMBWBRuhAdGFdy3Hc1rzXPkScelk6354S6S6y0f6nmRRGreXJsD0onybith1RLX1hovB4/we89lCLo8NaAEWp99iH/1kMtBmRGIKf2k6Ypw/TmOAmhCK6JSPMHIyo/1HyZWE/qk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=VVl0Slwd; arc=none smtp.client-ip=212.227.15.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="VVl0Slwd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468393; x=1710073193; i=l.s.r@web.de; bh=TMiHPegQUo5WD5H3L2SdR8bYUsLkTA/0O79Y1122BU8=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=VVl0Slwd3cqcaLcyMnhED/D3i8hNqUGotWICt1dnB5TMd54Oj+RqsDJPDQYAoP5y YLdSGgqecromIKRBw72+Ukx3GYfxG8EwbqZlu4RTkA15GuAAYcsdGlNGg6d/LZ3M9 pj6SXxIxUg8iSq63fis1R0/N36W18+NkFTQ74qWCMYZTLTpz9qL7aAK8/THggA+x6 N261HxnPPr/0L6quVicFi1+klbpeIaHm7D352RAs31zOYv2MHrKevd919v9tMWnR8 25s0ZuKUrU0it/dOLSFG/0GnTDegv97aSiRbi8OgSgrPB2aCAd1XuosHjyj9jLj0k XV0Sf6gnO14Te3Z1OA== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MP384-1rUbBt2TKW-00PVAo for ; Sun, 03 Mar 2024 13:19:53 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 3/6] parse-options: factor out register_abbrev() and struct parsed_option Date: Sun, 3 Mar 2024 13:19:40 +0100 Message-ID: <20240303121944.20627-4-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:Cu5WycJZR5jjsFrF/WXLO0HbHUJRJ0fPxS+2Wyf4QHvJoLns/P9 Ep4pdEk/ZV4jQI9Efw9L/uqSy4OZ6x0hEQsMxAGfyYfLtWMwJ/oQaevQUekxYbuX53CyG0S RmUtSqlVnlrcSjZPTl0AsVjdHw9AM0UYZEFaAIbL41LS7g+Z2ZGRRf8tN8S04xoBCE3+Tyf ELtuqt0iXQPdxNeXRLvXw== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:0m67X2ai2Dk=;3Jhw3os7sjyDif5FsDB+xWJR/sO H2Mt64EK0m07516/9Lznm5sHL9Lpk+j4CZQoVc+s9ne4GCL4WEe9dCNNpEHxN8Nb9Tdc1HRB9 74CXV0TXatDTQV0YkSWiqUG17tRNsC5BcM6W6Y8wPkChikUkoM5SzQVLxVZRHRVqLY7GoWcMo k9nf++jmEWHAMHRmPH59rGpocYoLVGIBawHRZFUZioG8BvZim0sIbI5W61WlaGaOsOMUAOlWD wGNVgz7XDHoKaiivJ3p7jUVidPBTg6Sudv5lN9PGH9FQ5lM2MyhQq7YKj5jxru8wfzAeXdoUc 0eF8a6zecmm1PTF+uVSER46YIebYgejF+RcN8uENCyDBUJT45Y7EuSRz7z6uDCEM+NyqZb5Mq LEtqqVQJIUZkyfEc9GpqhomfXYBqw78tl1tct/64Dau6SWQvXEVQLfR+S8xjbF+hVznRu3Qlu oAxFh5v0C6S5sZDkRWYzA51ukF5iYMKwo6/1er0L3ha7h+JtxIIeY7u4QGb9GVlsQsF/VNKQg vyc49QnZL1Cr+fKyYo0rHX+bU8dn8MpTvaw0VZt9EB/blwT/o/p7qrLc/3PpP2iha8TbSVl9H OMZIjwKdlqBXXX8qETPqCp+872IjilRVSTxVPCSB4cUXFD94FzYBf87HZDkXwjbPV+zWbnFRm 0hl3QOhJsjnOCYMI20JWInve5tmW/7zExId1DvedFXPz/d6E7goIYD3C9I0JNLyWQgbwuh/Md 49vq8qw64BSXXKsmBYb1R9YJh3i5PBvpQYkT74KeP/hsJwqBtoX+qRdxT4JLY/lOMo0JNgoya VG0Rut4K4RNraDWswqWIKRCVgG8eSblcTKVDfo1Pgv9uE= Add a function, register_abbrev(), for storing the necessary details for remembering an abbreviated and thus potentially ambiguous option. Call it instead of sharing the code using goto, to make the control flow more explicit. Conveniently collect these details in the new struct parsed_option to reduce the number of necessary function arguments. Signed-off-by: René Scharfe --- parse-options.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 34 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index 056c6b30e9..398ebaef14 100644 --- a/parse-options.c +++ b/parse-options.c @@ -350,14 +350,40 @@ static int is_alias(struct parse_opt_ctx_t *ctx, return 0; } +struct parsed_option { + const struct option *option; + enum opt_parsed flags; +}; + +static void register_abbrev(struct parse_opt_ctx_t *p, + const struct option *option, enum opt_parsed flags, + struct parsed_option *abbrev, + struct parsed_option *ambiguous) +{ + if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT) + return; + if (abbrev->option && + !is_alias(p, abbrev->option, option)) { + /* + * If this is abbreviated, it is + * ambiguous. So when there is no + * exact match later, we need to + * error out. + */ + ambiguous->option = abbrev->option; + ambiguous->flags = abbrev->flags; + } + abbrev->option = option; + abbrev->flags = flags; +} + static enum parse_opt_result parse_long_opt( struct parse_opt_ctx_t *p, const char *arg, const struct option *options) { const char *arg_end = strchrnul(arg, '='); - const struct option *abbrev_option = NULL, *ambiguous_option = NULL; - enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG; - int allow_abbrev = !(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT); + struct parsed_option abbrev = { .option = NULL, .flags = OPT_LONG }; + struct parsed_option ambiguous = { .option = NULL, .flags = OPT_LONG }; for (; options->type != OPTION_END; options++) { const char *rest, *long_name = options->long_name; @@ -377,31 +403,20 @@ static enum parse_opt_result parse_long_opt( rest = NULL; if (!rest) { /* abbreviated? */ - if (allow_abbrev && - !strncmp(long_name, arg, arg_end - arg)) { -is_abbreviated: - if (abbrev_option && - !is_alias(p, abbrev_option, options)) { - /* - * If this is abbreviated, it is - * ambiguous. So when there is no - * exact match later, we need to - * error out. - */ - ambiguous_option = abbrev_option; - ambiguous_flags = abbrev_flags; - } - abbrev_option = options; - abbrev_flags = flags ^ opt_flags; + if (!strncmp(long_name, arg, arg_end - arg)) { + register_abbrev(p, options, flags ^ opt_flags, + &abbrev, &ambiguous); continue; } /* negation allowed? */ if (options->flags & PARSE_OPT_NONEG) continue; /* negated and abbreviated very much? */ - if (allow_abbrev && starts_with("no-", arg)) { + if (starts_with("no-", arg)) { flags |= OPT_UNSET; - goto is_abbreviated; + register_abbrev(p, options, flags ^ opt_flags, + &abbrev, &ambiguous); + continue; } /* negated? */ if (!starts_with(arg, "no-")) @@ -409,12 +424,12 @@ static enum parse_opt_result parse_long_opt( flags |= OPT_UNSET; if (!skip_prefix(arg + 3, long_name, &rest)) { /* abbreviated and negated? */ - if (allow_abbrev && - !strncmp(long_name, arg + 3, + if (!strncmp(long_name, arg + 3, arg_end - arg - 3)) - goto is_abbreviated; - else - continue; + register_abbrev(p, options, + flags ^ opt_flags, + &abbrev, &ambiguous); + continue; } } if (*rest) { @@ -425,24 +440,24 @@ static enum parse_opt_result parse_long_opt( return get_value(p, options, flags ^ opt_flags); } - if (disallow_abbreviated_options && (ambiguous_option || abbrev_option)) + if (disallow_abbreviated_options && (ambiguous.option || abbrev.option)) die("disallowed abbreviated or ambiguous option '%.*s'", (int)(arg_end - arg), arg); - if (ambiguous_option) { + if (ambiguous.option) { error(_("ambiguous option: %s " "(could be --%s%s or --%s%s)"), arg, - (ambiguous_flags & OPT_UNSET) ? "no-" : "", - ambiguous_option->long_name, - (abbrev_flags & OPT_UNSET) ? "no-" : "", - abbrev_option->long_name); + (ambiguous.flags & OPT_UNSET) ? "no-" : "", + ambiguous.option->long_name, + (abbrev.flags & OPT_UNSET) ? "no-" : "", + abbrev.option->long_name); return PARSE_OPT_HELP; } - if (abbrev_option) { + if (abbrev.option) { if (*arg_end) p->opt = arg_end + 1; - return get_value(p, abbrev_option, abbrev_flags); + return get_value(p, abbrev.option, abbrev.flags); } return PARSE_OPT_UNKNOWN; } From patchwork Sun Mar 3 12:19:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579742 Received: from mout.web.de (mout.web.de [212.227.15.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A087CD29B for ; Sun, 3 Mar 2024 12:20:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468405; cv=none; b=AAxby/M0MI94VVk63Qze7tXGlUMEekm9nVdIIT1gkU79hgdbMQL9B5oe0VuUY4pBGYWpBbK0reVHmcwKF/wC4L0ghEjUjTAENBRM9act9FFBKbrYgT+kjPq18cYWbD6AcjwnLREGk17UlPVPmq8N1ZiUtXqVY7Gqdfd4bab+SuI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468405; c=relaxed/simple; bh=D0+RSFEIs9sR7ZF3DecpRGqors/RGB0Mzlqvo3OZVQQ=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hJAmdaxsF0x/d7WVF6R8dRcFgobwpZv5GJSUdEbyGLdgaaiJmlpBIOKZ0bmXqj75n5XL8NoY6TqjeNP5qDcjjr89TuPuXyK7XErNXd7LZ2kyEICmsT28da4OJF9Xob87Q947KnFhP0g8zgcwFQUjN7yGZUvgGZ6sinI6/a6HALY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=sX8bnrgQ; arc=none smtp.client-ip=212.227.15.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="sX8bnrgQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468393; x=1710073193; i=l.s.r@web.de; bh=D0+RSFEIs9sR7ZF3DecpRGqors/RGB0Mzlqvo3OZVQQ=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=sX8bnrgQmGEp174yXel0dZTsJlmj8c/vIZlgxe065PERV4SHtWdVBrf6qd/rH1rv IccpWX1+5nfKa2KZowdxs8y3evl3E+BReUVghdyD8W3bPzDKLcScmG238OW80Vy7g 2jiQ335CVbcKd9+aACwUYKpg44FgJwRubX7isMYFLJ+vjY+m/LdB/T6sH+8Dp9e3S L4+H+RQY1+AKBEHzSv5nhc5cxRS2yf4rnYs1mV6DaFHlB3ULKCuEsVHFsybMpZx2h 48ibyPBEzLorD5F1fDEzheB7B0Ryfv1EHLEJiK9Eo2ps1O1mbmM+mD3jDHJ0sVk6/ MyJfFOGldKLjMHA1bg== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MN6FV-1rOGb631Hx-00J9Vz for ; Sun, 03 Mar 2024 13:19:53 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 4/6] parse-options: detect ambiguous self-negation Date: Sun, 3 Mar 2024 13:19:41 +0100 Message-ID: <20240303121944.20627-5-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:l86F0OcDu6OV2l230yQFE244kJ39Tf42HEBA/NTQRzofYKs8vBp 8f5u4A+v5/FEJ5B8f+eayREDvByTIXtS2q5H7yuE0BBJbBaPyVF67wZb+n8ffZRVr7l/7UQ rhoSt6mg4hOASIQyrj1EvMcoLDXT5y7OoKsXlgzoEwmibcl2bShNiT9K9RMg+jVBQiIPrFq q5no7q/ImhwTCfucDjEDQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:vXmCerxJzsY=;us+bnBP+TM7Ixu/yHwGkWFvpcP8 UoYYX0BmHvEl4DGgzHa03fIS0RW5yAFLftCltyYn+au8P42PdytXk74w6qX6mI+XIBL6nBW/V Tb/AEI2WC5GV14PR9uHUAIPUk6J89niemcuB1AIjYJMBmRipNUgfAv70oesgO8HoYEnyHg33A VoTaDkC/OqToPrvkp0Vp2TxxuM5VPe5TwFoXUeIwcsuO945tmcTPyqPm517SZdhNWP4Jy4BUN T5JLk6IdP5OBFUXKbZG9FUOUqpEGMSpo0seJ6ZUMi4wHS5DHAakJZpmVntOeaKpCq3jCC3m+v dFgLYCd12G/4FN00cDM3788wdX8x0RQWHXdC+ob6Bq4u+JkFjoFJsEMbF7IPXubpD2XzePaJU UGQ7CupuGpZPS9i7AQOOJzYfj+uvHn02cibfgQFy5LhtEIcNH9INKFy09N/XP0lsnjBGMyzeH S11Ya2elFvScqWSSgkSSAWqAQuGqTih6Vs7aRO7pa0NJYrqzgTbxtMCT/uobEMyMkZ5qbjCtj YZwZ5uGdD39RrGp7N5bpabKHYc5yX6qTuRGBdEys1duFtzgCEsyYWvaakalbGi9jVKtcVkqDj 2vFEWSaW+zhdfRB2GL15lCYou8a3o7LClTPljFkNpCI38BYjUG3mP8QLDo9ZHUCa5QOYhvh0e 8HyCkK1zYqVQ43RKZXN7clr/5lETz4molvLrbauyYPC0GomiJN9v/WxgpPjcOh5Q5mJcNXO27 TaDcIKZFJm3WvRTY1ijlNafUzUA/+A0QhmTh/yoRIo/TzZ/ZOLr1MikDnIlw4tAJHYPxsbVI+ nUtXcqvU1UruCY0jcWxCci2c0ruP+Roql9VwI3asUHAa0= Git currently does not detect the ambiguity of an option that starts with "no" like --notes and its negated form if given just --n or --no. All Git commands with such options have other negatable options, and we detect the ambiguity with them, so that's currently only a potential problem for scripts that use git rev-parse --parseopt. Let's fix it nevertheless, as there's no need for that confusion. To detect the ambiguity we have to loosen the check in register_abbrev(), as an option is considered an alias of itself. Add non-matching negation flags as a criterion to recognize an option being ambiguous with its negated form. And we need to keep going after finding a non-negated option as an abbreviated candidate and perform the negation checks in the same loop. Signed-off-by: René Scharfe --- parse-options.c | 3 +-- t/t1502-rev-parse-parseopt.sh | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index 398ebaef14..008c0f32cf 100644 --- a/parse-options.c +++ b/parse-options.c @@ -363,7 +363,7 @@ static void register_abbrev(struct parse_opt_ctx_t *p, if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT) return; if (abbrev->option && - !is_alias(p, abbrev->option, option)) { + !(abbrev->flags == flags && is_alias(p, abbrev->option, option))) { /* * If this is abbreviated, it is * ambiguous. So when there is no @@ -406,7 +406,6 @@ static enum parse_opt_result parse_long_opt( if (!strncmp(long_name, arg, arg_end - arg)) { register_abbrev(p, options, flags ^ opt_flags, &abbrev, &ambiguous); - continue; } /* negation allowed? */ if (options->flags & PARSE_OPT_NONEG) diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index f0737593c3..b754b9fd74 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -322,4 +322,15 @@ check_invalid_long_option optionspec-neg --no-positive-only check_invalid_long_option optionspec-neg --negative check_invalid_long_option optionspec-neg --no-no-negative +test_expect_success 'ambiguous: --no matches both --noble and --no-noble' ' + cat >spec <<-\EOF && + some-command [options] + -- + noble The feudal switch. + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + git rev-parse --parseopt -- err --no && + grep "error: ambiguous option: no (could be --noble or --no-noble)" err +' + test_done From patchwork Sun Mar 3 12:19:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579737 Received: from mout.web.de (mout.web.de [212.227.15.14]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC50AC13C for ; Sun, 3 Mar 2024 12:19:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468400; cv=none; b=H72eOErFjw9hEv++iAwSrY002iHanD7UJcl8FmKfmDouPNKFErApPluut3gRyavbpn8qYSZ6JKeSKFenM5wk9IYXP7heLBk67//0DiMC251QnpqY0TOcoJfA8eu6eet6VLlb7HsUL/g2CGkq+yy/shjGr555Hmg4k6aIJ1JtXGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468400; c=relaxed/simple; bh=RoMlF32F9cMG0eaEdtMsrcQW1AITe0vez2c9SuVV3KM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZsAvVqASe3uKOxySJmGnBhtoJCinDPMv6XbXZNBjvdV0QLffI+cMAiXEHFcOM2Zm1E70K761f3W/QYmrBrZBPI2lGmQjzPHtj4xPhIcAiyFRivD9eBjt1OwnXtOSXOhzOjkIcP0+B+2jd5NGyFEdolMYbe2CpvYKnAFD26BUmd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=bihRt+BR; arc=none smtp.client-ip=212.227.15.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="bihRt+BR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468394; x=1710073194; i=l.s.r@web.de; bh=RoMlF32F9cMG0eaEdtMsrcQW1AITe0vez2c9SuVV3KM=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=bihRt+BRSHBV2+RdGx1mudXKQnc7AMltQP/01hXeXZQJyZbaoLdPXUVu0q7K/S6H XJeMScXVSzmQJqVn42TNqCPb5R1OahATimfipZwSRPpir7w6zYb2rSnu0WZaIuKBL LhNpdp0Mx6oFHlms/TsxIK1kVWYoApBun51KWUY1tZDBMARDimFOeYZGr5G//dJKg Q6X9S7TwJ/2nDMbmAhXY+hWrZQyT/cIAKPA0oSPe4/ByeRuxkfztN39+Z3F7N7YIQ wg48ERJ7erdm5CKDHykfjxf6WKZuP3lzME7q+f2xEfKFxDvUaN51HeTApcsLYi/DL q6ombYJlpr3eqGEgzw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MxHUC-1qwdLl3Z9s-00xSTu for ; Sun, 03 Mar 2024 13:19:53 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 5/6] parse-options: normalize arg and long_name before comparison Date: Sun, 3 Mar 2024 13:19:42 +0100 Message-ID: <20240303121944.20627-6-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:/JedbBqZyWoGLdEkLJHDWCaF/z4sHCyX9cBuTZff22ns1gCNN6D UrqSZbcMNA2QkHYKwfdkGOcuPxrCODYojNSHWpW4uHYKYGvdY7QhcNL53zw6YHdgYE78F61 2tE882dQ6H0Dg+4gROdWrzfQ0X8uiFrKzS8qDQhgMk5IFfNLHhfZZmPUMskie4ZZLssBTBO be1RdTQ8vP0QMg80g8Rsg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:B3eQ1VLbkxU=;68ltKJdFA/7TbDtb/PHSnCVXAbD +BKjCgt8d5ZpY7ds+x0jXyf3CC16jIYGQhg01LmHPZtQSCxAg0hY2v2q8nCMWpTZ/pToEBfD5 lCIDrauc+DwL2w7LftAUTBkQv9oIO6LC4HAxTnDmixnKjTP+09bQvE/1WIWsHI9tlzcMe0xpL dCNww5eiH1pU3XG+Kdy8ILgGQjMieng2S8+DdUkd/qqWCi6+1N8sxiRhDwLo7dScy2M3dWlXK eQ0cwCRTUP7lLRABdS2IU4OkjQVMSxAhDWuRBuj38hWVPEN69EXkoZfQwMp2VK41McNGva3lA cQY+2d5ksl3GLK60KjeNog6AT/fsE+trcvyxu9WqxPTW3idV+eqhUnl/2lE5HpBaYO4SY2dBr 6Iz+WRtjxDFipjh77vm4oFyK0RDEL+MFU32vm7CcngmR3dMzITgnYm6JnpZlWtnJyDZFDoOml 8yKZVhom3Eb3nQTWhO2KNX+bIWHz/h4FvLoEB/3Usj8TlWhuWnsUeD7nSs3geCUYy+Dcr9PMO pL9dNSpGTlaU0uRb1JOxMofh2tWgy93FGK4lrRcRmhaBjo0rVCXbrSLqEn89xN5OXJz58nZ/J sCk5Z50q3KbrPaKh0lWu4fT0V/uxUt14tPwag7AaAnikhh3+FT8+kP7uktolzja0GtMeZpz14 +pZPqpDaje51TNw4JElJpWFfqeZ47xt2L3w2YvzYpeay2ULKKeXXSx/2zGnpyVvt9RnOiI7Rh hYAq83yrMO/Hey0eixy8Gziv1nsTS8AcAlRFWEGWI1wYr006p4gCGWyFJiHd9QLIoIsYWh9W1 NV+BsvVeYnrHet848odAyX6gqVefxYGM2tsgV+QZ6sbZY= Strip "no-" from arg and long_name before comparing them. This way we no longer have to repeat the comparison with an offset of 3 for negated arguments. Note that we must not modify the "flags" value, which tracks whether arg is negated, inside the loop. When registering "--n", "--no" or "--no-" as abbreviation for any negative option, we used to OR it with OPT_UNSET and end the loop. We can simply hard-code OPT_UNSET and leave flags unchanged instead. Signed-off-by: René Scharfe --- parse-options.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index 008c0f32cf..d45efa4e5c 100644 --- a/parse-options.c +++ b/parse-options.c @@ -382,28 +382,42 @@ static enum parse_opt_result parse_long_opt( const struct option *options) { const char *arg_end = strchrnul(arg, '='); + const char *arg_start = arg; + enum opt_parsed flags = OPT_LONG; + int arg_starts_with_no_no = 0; struct parsed_option abbrev = { .option = NULL, .flags = OPT_LONG }; struct parsed_option ambiguous = { .option = NULL, .flags = OPT_LONG }; + if (skip_prefix(arg_start, "no-", &arg_start)) { + if (skip_prefix(arg_start, "no-", &arg_start)) + arg_starts_with_no_no = 1; + else + flags |= OPT_UNSET; + } + for (; options->type != OPTION_END; options++) { const char *rest, *long_name = options->long_name; - enum opt_parsed flags = OPT_LONG, opt_flags = OPT_LONG; + enum opt_parsed opt_flags = OPT_LONG; + int allow_unset = !(options->flags & PARSE_OPT_NONEG); if (options->type == OPTION_SUBCOMMAND) continue; if (!long_name) continue; - if (!starts_with(arg, "no-") && - !(options->flags & PARSE_OPT_NONEG) && - skip_prefix(long_name, "no-", &long_name)) + if (skip_prefix(long_name, "no-", &long_name)) opt_flags |= OPT_UNSET; + else if (arg_starts_with_no_no) + continue; + + if (((flags ^ opt_flags) & OPT_UNSET) && !allow_unset) + continue; - if (!skip_prefix(arg, long_name, &rest)) + if (!skip_prefix(arg_start, long_name, &rest)) rest = NULL; if (!rest) { /* abbreviated? */ - if (!strncmp(long_name, arg, arg_end - arg)) { + if (!strncmp(long_name, arg_start, arg_end - arg_start)) { register_abbrev(p, options, flags ^ opt_flags, &abbrev, &ambiguous); } @@ -412,24 +426,10 @@ static enum parse_opt_result parse_long_opt( continue; /* negated and abbreviated very much? */ if (starts_with("no-", arg)) { - flags |= OPT_UNSET; - register_abbrev(p, options, flags ^ opt_flags, + register_abbrev(p, options, OPT_UNSET ^ opt_flags, &abbrev, &ambiguous); - continue; - } - /* negated? */ - if (!starts_with(arg, "no-")) - continue; - flags |= OPT_UNSET; - if (!skip_prefix(arg + 3, long_name, &rest)) { - /* abbreviated and negated? */ - if (!strncmp(long_name, arg + 3, - arg_end - arg - 3)) - register_abbrev(p, options, - flags ^ opt_flags, - &abbrev, &ambiguous); - continue; } + continue; } if (*rest) { if (*rest != '=') From patchwork Sun Mar 3 12:19:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13579739 Received: from mout.web.de (mout.web.de [212.227.15.14]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68C5BBE68 for ; Sun, 3 Mar 2024 12:19:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468402; cv=none; b=XDXkgOuEvVfAS56nE+1Up8xDykacq88x7xQ13hgMWg4Rz667M03I2ATEip4kcouaH/ohgyh0YsCt4z7RJfZo1WkkIOV0pi1HyBi6CBX//9tUAYOTulA/5We1B9Lqgzk1QwXeazLZBt6dnXw9/fS8E89PXMvro3KXr/kf5cuIxjs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709468402; c=relaxed/simple; bh=D2xLPR2ewtSWiGz6tI8zVvcPZLreB65lFxearMCyBrM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iHdnhrkQXac2y27CMUpE49HbyaWeHfjbTdjp3sHdV1gALnpZP0clfd0DRW2cvpOo8BSRZWgl2EImXI2DhJFsCbeUJTfUis25Cnj1gs9YYfK3ShuDi3VT1FGLE0kTx+xh5E+xib1WPfQnX0N8byq0O5sCF/4VeT0qRbv6LysqDH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=QOxqD2aV; arc=none smtp.client-ip=212.227.15.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="QOxqD2aV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1709468394; x=1710073194; i=l.s.r@web.de; bh=D2xLPR2ewtSWiGz6tI8zVvcPZLreB65lFxearMCyBrM=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=QOxqD2aVb4xW+H/WYa8TgBDyXp7yBwUmfqk/Z7wlyu4Ig63EsIKFpr2Y1f9/kidy vyvcikdI/O1Zl7nhaNhKzrnRJaGBLEmZII6RLQQQf6NkorvXP3cRjmBQ6lKnxTUFU WOW4q9Rc8cseovlWHUz9PMD9dTrAXxf4w3ZJ+GdfIp9F39RHKt4DlaB9y41Il2VmA 9/wXs3UAeQhq7GJMfJ+1yDM64HU7NIIrwwocK77h5w3eey+BxNAgbZHuCrMBGVR8Z Brquy1arc9O8wpBnYMlBLVJ+J0h0B++XnQgEFeWF6g+yUMkA4NjvEAZgiu1mtf0Xh 1VtH6FkXtRk3oz4dWg== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb005 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MumNL-1qqqio46z5-00remr for ; Sun, 03 Mar 2024 13:19:54 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH v2 6/6] parse-options: rearrange long_name matching code Date: Sun, 3 Mar 2024 13:19:43 +0100 Message-ID: <20240303121944.20627-7-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240303121944.20627-1-l.s.r@web.de> References: <20240224212953.44026-1-l.s.r@web.de> <20240303121944.20627-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:P7DRnYce/EJlAYB3jNlcvP2KODJyhj42And/hehqMPwHFL2wJvW F/1fd849hAUExkBZAD3dwU9cAn8JwIf+mZ3H7i+RQkquSWciKUXgTDRhxv4xA+BDPLam11E wWXNx1se+SBwAl6+wvoYJPIp92jRBVq6Q1Azqv3frGyZsadhAz6BRTLgGNQhmgtQIQG68B3 N4B8u745V86lsqKRC0tNw== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:6XKaCvrivbA=;9w7nqGShra/pMvfCWkqNmSW345Y zFyLD/mtFWMOGB4w3NZCr/3fYGc3l1KpscmQ45K/V9NFZV49gcELEwySnOOwjwEQGwRr9R/B6 4uzbLXhhsmZaiqytLERha0DfkFRLAwMf0w88E+ngs9mE8Ec4Av+7Fg63cNeHUDH12pKUcFyzX 4Z4qMxNuX2VRg9i8gxv6LAU/MSkg0tALSVciAw5OvmViNS4CD2+Li+2wJBemyb0c6Cxc1uISy wPihGw8WPOcj20FP0Y4yPOTe+U3xuz5rOKdKJO37JE9aPhxIRcFE5DwBLKz9lgngHajDwmSPE aqRmLlu/nyqK/DigXgbIgZeN6x9phquzRfXxWfA1BOd0K9JTZJLz8LErUU0KG1FWhEvJ+F8TQ VeSLox0k1a+4uGgfDQcO8S4in6BpYsUCvmomhb9fwLAWdYSCAY66/ozegQYYPCuNytFu0Hj91 GDn7nRRrNpQkV9gPYJZk+Lqfo3MrGhIhSJ2iKiWeumbP7gq5u54vh9ecU9nVvWRiglaW/LWF0 OzITAwva0NByQ/l2yvJIEcas+UkFEjknxGsblrmUrLE2Ex8QJkjP2WWS7i1PgIJ1b+GIP3faR d9lxB0OD03UnRNal2su3uJ7UXtN8XvYs/wHolWz+YzR+UzfQRTHvSxHeLhKGLEEaVoLsUOhhu RRvyTyzxCM0Z8oxaCs64KrQh1+on4VEi5WzPfbS+WDmTkKU89nZaGKMm4Bhu1y3FonJsi+Myw RoJEVRYKdWaNQHUltjOjK1jwwI/eQ5uLbGKBzgGowWWtJZ1FmhGNs9pu1uB47jrQYI6fM5594 k1+75SYxcLtw3nRu5aEGOnB08J0i4IKcRe7zYpW0uuG4g= Move the code for handling a full match of long_name first and get rid of negations. Reduce the indent of the code for matching abbreviations and remove unnecessary curly braces. Combine the checks for whether negation is allowed and whether arg is "n", "no" or "no-" because they belong together and avoid a continue statement. The result is shorter, more readable code. Signed-off-by: René Scharfe --- parse-options.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) -- 2.44.0 diff --git a/parse-options.c b/parse-options.c index d45efa4e5c..30b9e68f8a 100644 --- a/parse-options.c +++ b/parse-options.c @@ -413,30 +413,23 @@ static enum parse_opt_result parse_long_opt( if (((flags ^ opt_flags) & OPT_UNSET) && !allow_unset) continue; - if (!skip_prefix(arg_start, long_name, &rest)) - rest = NULL; - if (!rest) { - /* abbreviated? */ - if (!strncmp(long_name, arg_start, arg_end - arg_start)) { - register_abbrev(p, options, flags ^ opt_flags, - &abbrev, &ambiguous); - } - /* negation allowed? */ - if (options->flags & PARSE_OPT_NONEG) + if (skip_prefix(arg_start, long_name, &rest)) { + if (*rest == '=') + p->opt = rest + 1; + else if (*rest) continue; - /* negated and abbreviated very much? */ - if (starts_with("no-", arg)) { - register_abbrev(p, options, OPT_UNSET ^ opt_flags, - &abbrev, &ambiguous); - } - continue; + return get_value(p, options, flags ^ opt_flags); } - if (*rest) { - if (*rest != '=') - continue; - p->opt = rest + 1; - } - return get_value(p, options, flags ^ opt_flags); + + /* abbreviated? */ + if (!strncmp(long_name, arg_start, arg_end - arg_start)) + register_abbrev(p, options, flags ^ opt_flags, + &abbrev, &ambiguous); + + /* negated and abbreviated very much? */ + if (allow_unset && starts_with("no-", arg)) + register_abbrev(p, options, OPT_UNSET ^ opt_flags, + &abbrev, &ambiguous); } if (disallow_abbreviated_options && (ambiguous.option || abbrev.option))