From patchwork Sat Feb 24 21:29:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570643 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 824E61DFE5 for ; Sat, 24 Feb 2024 21:31:24 +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=1708810288; cv=none; b=EgRLgiuvVRKXzkpT3Yuo+pjUqJctI+yF2pCCvN2/REBDUA0tU6fhEY44hp4lUIW4myzCvTOuo1GHsp+RInI6kWAPx/2lSLY6153g4dD7/4eLtDR+5UlgYLDCzlK7FbB1Sit93jmTmozZALvnfwOEbI2gRJDdjqcIDLk0WZOj2cY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810288; c=relaxed/simple; bh=tTi9OiaCdyb7jGOMfHR8PP9g/cVdTA2z5CpKid3x+68=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c14FWpUu6QQEIKua0IIbD4kujmthXpE4LBCmxtcMJJ7bps0R6vvX/W0x+uRrtYSQS/eOzycLZY8/wzXqrDMVzX+NVxb5W0Fa1+Avtae9ot/FKp546DOYGIB1OVIOIr5y7Y/yi7BJEZiRREseVMGy3VvvRC9XNUbc1e4ixaYNt9c= 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=FPDO73UZ; 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="FPDO73UZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810277; x=1709415077; i=l.s.r@web.de; bh=tTi9OiaCdyb7jGOMfHR8PP9g/cVdTA2z5CpKid3x+68=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=FPDO73UZJKNSoWvShuQcHvL2Wt6r6/2IGC4Bs7yHXVmjWn1iVIVybXVb2Joefoca gfcydbbC4/UahmWxVBj0Y7orKZSNhm6sPp5ciQQzFCjfXyfjOs3CeESbtm1mg4UoX tyj34QXeZsxGz5BSYcW3cLD2VpXd1dgx/LS9pdVpci/zcFk7XCusdUkOrmh1WtPIB 2D8NyXTrE4RMwwJZUB7nNnILxuj/8WAw/cnHc0BIxVHuVQS9hZQUQTGqF8FyaqKaR eWfV8bAm54N5wNjijlNFZy+n3YiErhENtVru0Fp0dOKs2Xn8CYJhFlNWQedBG+MB5 5V+Z5TE86dOCaB2I6A== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MHmq2-1rivp50kAI-00EuCC for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 1/6] parse-options: recognize abbreviated negated option with arg Date: Sat, 24 Feb 2024 22:29:48 +0100 Message-ID: <20240224212953.44026-2-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:0xNsPr0SfdfzTVIzT6aS2YLXIS5VdTK3YZqEMNDsIwFINKE/O1C l93ngNspKv9fiVtL9KEyCtY7wBf7DRYdC5mrju81jEhZcNK0lE7oa9/+8zG6WxljY/cQR3u Ju1T3pgwIHt3YuneEcnQ4/FZUYBgABXab9AsA9iP8kLvjegfgRV940uhG39v7/gmLTADodd WdG830z2UV8ewxa7+CWjw== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:HeFCa/JL7mg=;WQAnXHJ/aLUCwt0QlP2oO65O32e Ny2ZcO8kHXAADMUe2WqCC/KveOGWPx0yRAs/aKUeV1Ew0zozWvXM7jknC77znCpVnudJ/oE4j vRi77uWAiosJusmAcF5vaz+Hz/UPMjTWpzsoLVNdNXHHRJDiv0da11Pct9C6LNONhzeTTYczD HB9FISX12FSvFrXlrPEdfsEMYfWx6UHvq2WhNgNH7PEEc3uobQlPo2mYj0MLbMSC4PPNxiGMw 9toQpErIwl2vId2phbPQzYnRM11yXqJtfR/qYfli180IyOS/FsHWrMmQx5tR3++FPIINUxLco L8FsyGhEsnqJvzLVS7ZH6Vsoz/T0ToOg+f/cFAF+vgmSjbI9Kk9o5Vu6x3XITSdGl8+fWyYfV BOotKcTzVlWC+Y1wTM1UsOSVLtplfuToctV5m3+EW28ENmMSbcNkQ4OxVejLUCEkrVPoJ7hlj OnX8Vz0Tbp6VeOHa+7pZtStTWNT3yAseKyS65jJhgIVL44R6REFcZwfE/P6SJQh3u99AU/Dlk Jh6PbHjDuTsyJoyRI3x1rtCKMeRD0Zynw0x+I3AmyXFz63bLpuauuGsi3z6L08GJ33AvzTa4Y AqtCV9mx7Rsyyys3Sk+yToqnE6ykWbXeybcbdAXJIElgMAJ83xvUu41K1P8i8UyY2N0anlzWn ScQ7zGwlqui411Y+xNvOogZxstfWAiH7BmIa8VEmyROI/Dvmk14//zHTdict/XxCiLo1e1cZj SkO+QqHmXkm6OfJdXT+adjE5+tmW2OkjEP2AzuRGDB9iUIDbcgohBcrr6QvWUEB8+Q+CiqQUG GqrRX4oESZdOr8JVYSDNFmyzeYt7sJ4166uDtXhdOOmqw= 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 --- 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 Sat Feb 24 21:29:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570639 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 82528487BE for ; Sat, 24 Feb 2024 21:31:24 +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=1708810287; cv=none; b=qLoZ7FBYA+TZOv+W5QLmCarFXuwhTEnLZztvq6XGA+cbiowIYtzMx/d3zGK8m81osdNSOC1zO54RDt09qbMEnsBiyc33RjAUqFcogtMkRS3ddQuGqNcaln3SuquINCHPrBKLnQq6+mNR7xWOSaDcCSLzF82ec5MhZgPZ5BNZOQc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810287; c=relaxed/simple; bh=Nds33saJzzY1UNPZ69vw35wHgwdWlaG0fInbPvL1h8I=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ABryRMYt0XaAMzTcKGjuJof826u9/FPZzsywU8CzhQm+AZgu9ISWmaHbved/Mzp1ObsW60H7MS7IOn4OjiMLrNyKEvYwZxA0dofqUEUNnv4V5VtA0dyMAUD3EH4kYiL6Xlj1UHdt6U+3e4K564N6k8JtPWXma5NUysjBZlLEw3U= 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=voi0QnT7; 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="voi0QnT7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810277; x=1709415077; i=l.s.r@web.de; bh=Nds33saJzzY1UNPZ69vw35wHgwdWlaG0fInbPvL1h8I=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=voi0QnT75DIv6uiNmZFPidV945RUUE1n8oVgMZ/oGHC2mwvZs9OjumH7ibKYM/Y7 dp8Hvm4Z++E1QIGRrsxDg9qwL4HGXqmxOrr39RBNLDhVZG8kaiLa/ljDKelvCcQoP tZVJfnqUYRlJgqFmWofCym2kG4MIayHDgdcFmImjfavLuKMi++b7huLHSCosO2SVb LnUeskg3LoAfiLzx5Uw0yBrXnQdnkPFQ44B6GOm3hSX4sH8ilyYO4y/LhAwjJmitI YPk3iBFxtrmbAQkhZc1RDMtLIYOm6JCyWDNRv1iwnMAt36hOn3W8glEoROmPr5xrq O0i9Qb8dio6r7FGkWA== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MUCut-1rUooY1ITT-00RKFN for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 2/6] parse-options: set arg of abbreviated option lazily Date: Sat, 24 Feb 2024 22:29:49 +0100 Message-ID: <20240224212953.44026-3-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:I/NNLmVmlxgGsiQA3wbCF6WkrP4YQmEMEfD+CqCZBhs0vroCjI2 QHV7IE2lvcKxn6n8JdLh4NjUsogjQx9rakbrMABR8hpamO+Hrj+rEjfX3WMFFTHAeJIj8AD ZYHRWlnOk/xxfQt5jaGc94EGvtv4pZEeVdqnVN+sbCxWtn4z0T2MukxwQWWtFPwxtcjJ+og 4Ron2SxbPPzX6uD8oQitg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:dD5Q6L/5qRw=;eLkPAPRusOxs620jUS2UIYbVGuk 7xtUNHTA+djCTA1lNtqzFqk/zChYSqhuTNwBAYJlA9hJDouLADBKtIcFZZXjC8A0WdDtyeWdT nsrg7x1hIlRsfu4/yFAJvFOyV2XMx0MlYHFSOjanI0vo9vK+rhNKmA3epKQwiipKTFM7EPn9u 7N/JJIPqFrIuU8N4C5/PTdA+BuOgC116fTIOBM13mlCXZpB423Ne7pOWhtFWK12MyWjrLX8QW Sb6bT0rPH5SXmtcrZfloO8Flph94cgwvH8r1oejz3jQeFl7hUBN231ddZAXmgUT5NafMuK5I8 fS8TtgEcxPd4DJcYTa8eCYqh0BgCYQlrIztBJPsAIkp87sPgZ3vlxW3lJ7rVXFanDd9jny3TV QbYUyDpVrwciHobpu9Nk+mDTPeO5WkUQvCZYe5R4p7m8ZHldKVse7a9Elbg/7ESf7Oulx59mq I9UpJc0uihnB7nDZ8iEC9Bms9jXY51FoTrp0Jh9j7Zw67wSsuM0EzNYDl9xx5+2gaEb4tZrqf kbwzh6hRzXKRi1ei71gMVbGoOCFkfAoWdgy3fGMOJAn5SISQq5OR37GyK4iMBo5wcwLi9dvO7 MBytvbyaycuG+EpZ9JQlY4l7GyPzWduR/PVHCyxh81jsuIah6Du8lcHn0+7QpK3rP6OY7ZkAp 6K7Z44LHNyTVmEyCx0mwqrkmuTcgA6NE48J7KAL5MFQBLMYy2GXQSUcaWXli4qcfr/+XvQ4NS TV3WdpDHIcqfOfldrarcP3ZY/omZQq/A7RKIgXJDB7CTlDbHUJrzKpKLJGhIkTWXlDM9RiduO jdh6eenAUivb2GZat3T2cgiIJ0oh+7ixDlbeR85dk5lcc= 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. --- 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 Sat Feb 24 21:29:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570640 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 8248433DD for ; Sat, 24 Feb 2024 21:31:24 +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=1708810287; cv=none; b=LDyw+ecaWzGVL/JDTqyZLOnwKTUzhexF2aJZbu8/sQsn8AWyu8I+QVBBu9DzHDZ5mR8Q2SnBnpq2NtAXrk6VRaqkmjUvBGay5FoE2W02wPc1mgZlOu/YcWBy0iEqJz+SqCbEwEs5zeIncNv9wuvvTUjLN3EkCpdRE4VPc0DsVn8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810287; c=relaxed/simple; bh=/q3rGH4Zqz5++F5dtdbxjpC//Zf5HMkzQztTLDrEfF0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XNVf7Jl1S4NwEnRbm1FrNxosJjrDiHJPyHJvWv58LY4JUlrsp8soS11Uhx5oVWDQXGhSzoX5zBsvV0NzTh9axhbwIyurmxY0SkwwzRPLeaR8krpTycfmQuuaPM0M0uDhSjenU8KG2JMfO2zFJiy7VxsmomXcrnFsXr2Sm/A1Cmg= 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=FrwvfojS; 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="FrwvfojS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810277; x=1709415077; i=l.s.r@web.de; bh=/q3rGH4Zqz5++F5dtdbxjpC//Zf5HMkzQztTLDrEfF0=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=FrwvfojS7TJFdqL1eW2arKNfRr6PAYk1Vax4yNmmbyF2ie9iZLsE79if2vJ9u3eT D9s9mdr4xE/uOaAdVQzvJ33WhbH4ZZEvPzLk16G7Vg0cj//AFE8LSzp6iyoNqBQqp 988sY7L3t3ENxrIKesR9HNqj5rrPf1iVQ3oILPf8uxoFW1eQr6EyYsmME/hJdm1iK YQHYQX/vf3jAtVHrh+JwvqLAvcIdNAlN0nQR+gBx5Tjo1dEPBcKTCqCD0jy/Mwptp GOpCa2FH2vnJW3pWE8EUnUB42q9kZfXhi0emRL0p81nRM9YAkcWLhUn0BTcYFDAfW GQcHMUQ6rF4gn+qSbw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MDMzC-1rnJXH1qQI-00AULs for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 3/6] parse-options: factor out register_abbrev() and struct parsed_option Date: Sat, 24 Feb 2024 22:29:50 +0100 Message-ID: <20240224212953.44026-4-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:gxLpmXi3Cf+B9Ji99BK8fmDhKb+v5mHKeVa/gVXol1PmidPmzw6 lOqCeAihlnShTSNgceVPJFqQxXGE5Zcb7ICpiIPsq3eS/c/4lqKJL0STLqf56gPfiQ4Fouf EUGNn3VEfhOTufNOt2+wPQEb9pG/r32/R9UdgrQ2bvavNeI/Tk31G1SRdsi7RNqa/JLTz4d XVd8c4hevKep6AopxaD2A== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:AimHdJrg6bg=;OZLvAZVj+C29Ldrh5tQ0cuFU9Rk sTxXiZ01YyNxATvZoKzkY38mMWS9l9vMeVYHQeY/cQKemfbj4Os6vB6F7IrdWG8Dap4S8fOkD 2NMDa82qMivJqDf1FGi2N7yXbHAwr2DL49AVetvkS34GoY/jyi8GNITHsVr1VjJEV5ruogmpZ 6gKg6RW4gILfggW3a3F5DpYGHiKfflH8QKdrA8gB9uPDgYw25SUfpqh54PbDRNT+W0Au9dUKy 5INTfVRKRV2Y0K2y30ULbY3kVY6Im/G+OymWCFEVln8ut0jqERZl1T4jJkP/ydIcEFjJWu6OC 1lVFMyiJCVzWHpLiyHdoWIFxQyZDZCvFJ/Z2ORHEnc/l6NvqaD9qe0/OAfdfPHRm2niwu28KN Xx00/KDCbPliF1Oo+n3y9TlO65GK+EccFRs10xIBl/OOGWinTMcLDIqvnej4+mpuCsjXC2bfX ybPQhItRwML9UNj0oUNtxp7y6Q3zL36EBkDSJ75Gi/EDPu8XZ6+K0JvIMbUpNrTn8R8UqikzV Kj5WPr1PaxTn9KCN6SkGsErLwgTcLRx+vubKzvLsPUZIpBOiJMJI9BwHwGfuY1iW52HDN3TOx Pg6loRgggqqsCOpsAne9b6z5kQ7jwwTj7KA1s8V52bgNLlnrFLFUUQRWja7a/krJx+pafgiaY 5pw9+rPCmUsO3yONSEmJGPItUeRxgFhIMu5aFe7lN8zeJljfG4knWdXcQEGtT20ayk3jqgqVO TblUTKlIx5/q4m/12DMAJmzhAXEuqQd+CqDvRImf0WRDIzYtFeLu4i9R2omAjBpY7j9dm8c4N nhv8JofljgT+2VX1OqUoT+6/ik/dbQ6T9dvZgMEPpWLHQ= 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. --- 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 Sat Feb 24 21:29:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570645 Received: from mout.web.de (mout.web.de [212.227.15.4]) (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 C563F4CB36 for ; Sat, 24 Feb 2024 21:31:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.15.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810289; cv=none; b=spuzO43zmHfrFR3oHs4uqT0Ifsh/zFk4D+ulsuPVxOJfORyYpNO5EPu2FP9xLBBVlm0PnfjZXnF743IxBipCBu3+jiIyHJuIz4j03cC2JcnTn55nKAGHfMjkcCFvkUVg3TQkp1laBwwBuqfudgDNZK4jQP1ReI4cvU07uCk86uA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810289; c=relaxed/simple; bh=qsCjhrq09PqPIg6oOqOWS6me1VmgzooH+hnge3m5Fmw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J9ZDlwLko7/q90sT2Ki0MP/lMR9xbrJ4VTx9Uw25r/x8R/xMPMNIUpQW1JyHkigI62Q1tSMrM1FbUPckqHWUAJIALAjQTWB1LcoMeFyYrvuGfStF79zeJzmTsnTccodatNv2nQeTQG7NvE83sexOnEubRyy1mzm1p4QTAG8kCY8= 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=jxH9QCYs; arc=none smtp.client-ip=212.227.15.4 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="jxH9QCYs" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810277; x=1709415077; i=l.s.r@web.de; bh=qsCjhrq09PqPIg6oOqOWS6me1VmgzooH+hnge3m5Fmw=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=jxH9QCYstemstTHrbFhnP7mAWJHsoI2OIaATz/bHgB7smzkWdJ5/6BSxzu3FAOoX aBWY+GxuulaoV/K8sdRWbk5UtxPvgnwMTIm9pR5/e5VmW6fkDfjes9PSHibduH0yF TikW//zXVvVG+L74OVwghFLC4wx4jw/z4jHJG/db+fLnNsZPONgEF4cjZv6lX9vZI cWXYNOrb/1Xb55/76lJuzpwN3Zi8Rv1mk2z7rPNWZlxTDS9exb1BQAh8G4TXyM82F TyfvSnUYPonPGB1cz5uExJ5J9jG20ByRPBVuG0WIkmeRZsKRbCcv0ZWl8xskDx3AS yoOQcLYOCj1hIKSAvw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MPrLL-1rHffy2VKF-00MuO1 for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 4/6] parse-options: detect ambiguous self-negation Date: Sat, 24 Feb 2024 22:29:51 +0100 Message-ID: <20240224212953.44026-5-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:yqvaCAtHmEUvw1sXbZ5P+HB7bb7saZs563omVXZn4qsmh/yyYAo 5I2J+4c3jmME7wSgqSoNHv6zi52muL8qoadQRL7ESuVXv5/UTC9sBB7qBQ+pl/h52Rt21az sDtQDW5cSDPIhG4EE4Xt2yiDY5cJeSathdtXd7Zecqvhk/kGepfoNvrl9w0mpfVFq7f8a4D ZmKy0o3vTb/DSwAdgQNww== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:6hDJBiDWZSw=;0hR2ZZ4KyJ2oGbp1JzqMEGdIABn 5S48fub9rpX2wwmX6EtxMWMLmpa40YOcb6Pf79bZEa9IGdhnDS7sDuK1ftL8eO+ElAhehIREI GfW+qhn0m7+4ks39ZjprKsR4KWqWvzd8FM5ohigMjh8g9YWRaaP5nAYpAiJbBEfe9WPv8AvrJ FPC7KtGNrZ4p+5/O7h4YuuQkbqkZYe33xzjHIRSCFfYyrEUf+okk7jVscSsIbovjopi3PpKaY 46mUvmfcoMLtddIBBi7pqfM4iVwXKkRDzlq3sA0kSp2lahDn7KxVmR+V9G+iI8anShtZkwyTD d0IuMbRNPR9xEMv3Bqn9sDj9JKLGsSL/tY9VmJ254KC1p7q1Xlav6X3tS/bscDPE3oES8zZgV MrgLi96loG2sCSfi0qqZ0cFhUtE5HRny2D9FckF7orIo33ZUMUaT0WppWyozuq4OrCeipDBNH 8IhQUSffihe/bnKiSL+HMldGn13NMqoeUHdyRNPyWFgL+xvaKMPc584WSiC2E2GREhz33m0Jj frbZWA2zkP18X3ZxEvqFUlplSa3lHL7gZ232K3fFNoEOWDkhAqXmNlaExzhQFWCdxixlHPKjP AyWRyQ1T2+Dh6TqIscmhMrInXstKQ0omnT1H20gtcw2cy2bnUsRoFxqI54qz9B3J01TXw/Tiy zYP5bUD7ufYBRgbhZnsoxlQtQtBuJ9H/4OIyaQ9OnBSpZTmxY2AhFDree/K2u1w4EqqUwPtUq sIMX7ZonYB7JeQa9LUSu/pcENxbOL2SGiG0GeZQHFnGzzo3nAglu4vG2iEGHIwszqxL51fvsl IiUSK9Bsh8L5IGyMlETdGkrIIKF/rUGhDVlaPGn1utPDA= 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. --- 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 Sat Feb 24 21:29:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570644 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 CA8CC4CDE5 for ; Sat, 24 Feb 2024 21:31:25 +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=1708810289; cv=none; b=dOsQIkJSfDTlfmjPpnpeESaZsfUKSIzuPbf6Eo5l2jFcZaJdOP2u8rMH73ABTVfRiwTrGp6HqTTZpzfqFYZABrDAnlW+TX1vGSwjFUfB1tTTX+9qqz3uwBzh5e3jJgPkswxRZng5J6aM2IOCRXRxAN1CE/leNGEZqRZtALJEc4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810289; c=relaxed/simple; bh=gJi2rVxfHwoA8b65uLZpWx3RXhSwm2SHJMx16zn9L/Q=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h3YW5MxCMeoCZUA0DzrdxHdMAa3UvhE2ohn97q2SGI4RxufTEK5E9Ps9R3q1xfVP85+TtvqLtPBkjTd2q7sbfTV7RNiAdqPSNhEsYPYMTPgyySHgowALxyMtqqRwXJIrxYIhQ5y1/Fa63NapT0eMxCxaJvS+2tTipDRP7dnWQVQ= 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=rifvCcdN; 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="rifvCcdN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810277; x=1709415077; i=l.s.r@web.de; bh=gJi2rVxfHwoA8b65uLZpWx3RXhSwm2SHJMx16zn9L/Q=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=rifvCcdNxZpHIcgK6iZKeH+3Y0p0vzIp2BMVZzfbThMvaX4UlfxyNoZasmLNZi9J vZFnZ3+TWkwpQwG3LzLZ1xPhI7YD2cwC53HueW49BK1NM7vaBH84ScE3M2Mqcwfac gcDZd9Gy+KfmJvrLJrxuNOEwOMUMj842Tkubq1c9QQwapaeA677A6rrFAB/+TtgUP onz8LYAIe5JbT9bh5iKbe9/58h4eHPlRT4iyyeelUiT3Vzxer9El2QWeszwoadONx OfrHx5iT08xqpHBNhJNWx9NKclqPKSy+DlFioBcQ561ch6oY9NclYcBDIWB/ZItgP iqW8GtVwoA5GRLfAqw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MdwNW-1r5UPL356M-00azSu for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 5/6] parse-options: normalize arg and long_name before comparison Date: Sat, 24 Feb 2024 22:29:52 +0100 Message-ID: <20240224212953.44026-6-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:GvnvA/q7me6hbj7Ucjch7xQPFimJICOqdOflRvwINWMgHUf0t4c MqQ7wEd4A/YFp6WVAdCIYEHj6gU7DPdyL6bJW68CRcbbEctPXw08Cw+5LjuA/Ph048zocW8 PJA2jGqsl4NFh97uNGpF4wJ/ErCpICa1AgwrQkKB4J1viW1H6hYzdHmiTJI1iKUL0CXO3iX w9T4QWmjp1YNTY5AZHyhQ== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:Bk/NNM03I3Q=;FCxIpSWRMV97v6EGnt1x7cf9r9y WnjE8onyCLN81YsLmlHb+gaqBNah5/A9/2RMbEDxteKKosrJyWR6lloh4rugYwA8NtWK0jURT uBKBfbBVqjAoSJrIHmA9hhGVwPbhbLPoUM0affCZDcQbB6PtLuD4bh+pv6OZZ/ORPCFzoXSrR 6qzI35GG7qYlcX69b3Tie0TsJpJfSpOPAfNQ3hHko/q1uFgmkqygb+j7974CAlehidzdgsAwl YijKXOp0ktdojP6ak8pYgeUIDsJly3WVV8qx+dkK9Itvj7WTSsHOJdGmxlH2uTJGRdNd1c5tz 2GtPtyodfG6n5wgd97e5jLQ/CFBCp1NSpHNAQjQMHbtGqc+qbtqg/JaGfZ4Uz9ePT/Wcmh+OI EPG+517UJVGdpXV0UxI9tMz3fylLWLzNWv4xXTPApQbnCUCjdqf9hOYkaKevYFO8cRKpTEjcS KfbnoutZ8WUqvCy1fAEgEBDc4+jT9KzklPz5lb6YNHWuxtSTb5f7MlnVZhAhrxq6PFte60ryz gzHqHR3/0usf8CprbRPryVox9z1QhdYWjAj7EKY92vDZYbeyRLRuW93aTYPULGd9/aqQg2pUw v+1tFaR2tIGAWBNjpxfbtSlYEZMoMl6FQWYv7FUbCPAbw+k7H9MPjVzbOg7FZ7Qg/XRKg7CHR QcZqr0FkvSO0juRHh19ztu2glnRRIgUI/1IfTa4iUV1zYySkOQEdggP74buWr8VXtVUTjlY/3 t+lh5V8dRqN4aK0T/oa6b+B9JPhV+7RLFAh/GKSEXHKL3kG1RWq4xme1Hh5YyW5sytYL7dRIQ ObF9YWGLrxs/MiN5R15AE6YXUAF+r8Fof8KR36oiavgHU= 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. --- 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 Sat Feb 24 21:29:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570642 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 C62E34CB57 for ; Sat, 24 Feb 2024 21:31:25 +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=1708810287; cv=none; b=hhU93yssxDNeJRc6aH1zzSURohmxgpNqZqt1mCR4qkoKdzI1oVgbx42KsJFa7NVpLYQiEbn2/0zXPri8p9jhn8wTao9X1A6BE5RMmCw4WQrfFe/OMEOIdiJnblf7WMlGHsab01eBOdfz5HN7W1jM2wt/X411A/tWwHKRrXXdSk4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708810287; c=relaxed/simple; bh=I+y5jzEzysQcSA2yVOlY52+kmRTrscp/lyatL8IEBU4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AulqTY09xIc1U7tt33sS2lznZgfs0KHdL4QUBsooC4n6xe28hVL4j2UilY6Z74bftZ3YmaHlHv5URqtgRIcy/nPWMFz/87M61KEbvqONItbP6KeglEmxz0hBFz+OnlJIDUGmQKr218BGWa70Rc/axje9cl+Qb+ZgHn/lQrOZpWs= 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=rsFUQdOv; 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="rsFUQdOv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708810278; x=1709415078; i=l.s.r@web.de; bh=I+y5jzEzysQcSA2yVOlY52+kmRTrscp/lyatL8IEBU4=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=rsFUQdOvwj3dvnIfZXzHXXPKehq6Kqw0SlDipv1GjYiQcA5oPwbC/z4uq3+eqJRn idbzAxwRbA6gCZxfhFTRVQyEu0By0kzlhylkklr/5LuG8b99Ewf2HT4x+icN3fHRc xB5SC7bLMS+SHOcDYusTOO6WGtC4dbPDy9XCv9YylQM4w8FCkeee/nVqc4DWW+cNi a0Do4WFwvikRAmC2KK/GeOEezhh3K38FWVm4/gJm0oFYbfs+pYfpojdMbQQTSidq6 RNLn4CIZSqInCT0eRaF7E4OvGSg6t2UM3Y4abHzQLX1cFTJv70c4/NkdjStmOcZ3s S32SSPVUWcxUiSRjIw== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1MKM5z-1rKxze3eRz-00Lnvp for ; Sat, 24 Feb 2024 22:31:17 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 6/6] parse-options: rearrange long_name matching code Date: Sat, 24 Feb 2024 22:29:53 +0100 Message-ID: <20240224212953.44026-7-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240224212953.44026-1-l.s.r@web.de> References: <20240224212953.44026-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:YQNjp/9IqzV+UnH0DsZc28p5UE9yTkhl/G4JVQGKI+065bzzwZH H1DvR1ofQiFqNxN29/rnP1e4vc0ZPITx5q7m0071w6OW5BkWskfyf810Qb9WtwyQiH3XSMU h/LpAgSOinBxdh4SaF4MJGLZ63jyCOlhcbYpIRgTZ1ulr2CFvbkmoiCXeUg8ZB55o6wTxaq UChG/TaxReGU9YYW3Ytjg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:6bO9MtzmhmI=;z7R/VbJS3LhuO60e8x50gKyEHR7 8kklFXQ3Dz0unVTNtz1SqN0vFezUkOH58z3aEntJB+Z3IhcBkQfle18pb41ZfvWTCp1DvLFwq JEX+ZX9vfWND5+BmuE5L8ZezDb4L75XmyRZxyCMxdaBEdRm0h3RsKyiUcidf04xwWmXIZkabG 0DaP1x3iU/Bzny/yysz0YYO0cHz8TgMBoLquckSwdZl9mpmpnyVeBqaqpKjUmyDwSq262D73v TnIa27zdrC1bYW5vvr+FhaeZAqc0FgjfPdNFep5HKJomooHvkzC287u3TANkNyo2xxTRNLpJT qvbjSlcTqYkWDJccnksAx2IHPKxd4FXDghn2r4sCy7zy1q+h6SBqDNfKVuEXJ849njNaMCXRj Bih5O+Z3Lgug9Ccg/U/9aVJZAtvQzUkr9tNDY/2rexOTMUXYGV6iniji/PjVr20yLVtq7amz1 uYKUBAuDo/dDg8hgJ6lCtofZbmL2WyQl0TdApT3hB2IvWUOSdQyO2Qn71Fu87NcR8TEYUlQJm qzEMeQ2Be5X5WusZkYrp2j66tWhBD1beWxLMDg5vHruCJX2fcO6UElxw+RWyfxtFltqnF+6ys YAGO5kOrx8yK8AZxUGua86b/gHEAVKHrBoMwuwPAfgYkoG6r4g1muNFwEXqFf+JOefaTmMKfy wxYLt9MwgdBC/N4fNrENUGpTnhi40QSrJapkvXMogrr8OWo8Nl+ILS/E0UxmDLx5F+cujZ04m oZQ7eZ8OBsGxRaFxcLDoZUORu1oFyhPhN1Jdnfutjq07Yf7nSE+tDxNUmsPjJxMwxT3TIaVYK 2oaIfGPLNRZkp3zb2W+ECYb9QZegoOodND4yaJ4QIipVA= 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. --- 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))