{"thread":{"id":"59230","subject":"[PATCH 0/3] test-ctype: test all classifiers","startedAt":"2023-02-11T13:05:11Z","lastAt":"2023-02-13T21:59:11Z","messageCount":14,"participants":["René Scharfe","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"471977","messageId":"06da58d6-6aae-7b1d-6ce6-f07d27f05d97@web.de","threadId":"59230","inReplyTo":null,"subject":"[PATCH 0/3] test-ctype: test all classifiers","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-11T13:04:52Z","receivedAt":"2023-02-11T13:05:11Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add tests to cover the remaining character class test functions.\n\n  test-ctype: test isascii\n  test-ctype: test islower and isupper\n  test-ctype: test iscntrl, ispunct, isxdigit and isprint\n\n t/helper/test-ctype.c | 36 ++++++++++++++++++++++++++++++++++--\n 1 file changed, 34 insertions(+), 2 deletions(-)\n\n--\n2.39.1\n"},{"id":"471978","messageId":"21f316ab-714a-58f6-a8d2-466d738b4ed3@web.de","threadId":"59230","inReplyTo":"06da58d6-6aae-7b1d-6ce6-f07d27f05d97@web.de","subject":"[PATCH 1/3] test-ctype: test isascii","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-11T13:12:49Z","receivedAt":"2023-02-11T13:13:02Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifier added by c2e9364a06 (cleanup: add\nisascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\nspecial treatment, as our string-based tester can't find it with\nstrcmp(3).  Allow NUL to be given as the first character in a class\nspecification string.  This has the downside of no longer supporting\nthe empty string, but that's OK since we are not interested in testing\ncharacter classes with no members.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 19 +++++++++++++++++--\n 1 file changed, 17 insertions(+), 2 deletions(-)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex 92c4c2313e..caf586649f 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -11,9 +11,14 @@ static void report_error(const char *class, int ch)\n\n static int is_in(const char *s, int ch)\n {\n-\t/* We can't find NUL using strchr.  It's classless anyway. */\n+\t/*\n+\t * We can't find NUL using strchr. Accept it as the first\n+\t * character in the spec -- there are no empty classes.\n+\t */\n \tif (ch == '\\0')\n-\t\treturn 0;\n+\t\treturn ch == *s;\n+\tif (*s == '\\0')\n+\t\ts++;\n \treturn !!strchr(s, ch);\n }\n\n@@ -28,6 +33,15 @@ static int is_in(const char *s, int ch)\n #define DIGIT \"0123456789\"\n #define LOWER \"abcdefghijklmnopqrstuvwxyz\"\n #define UPPER \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n+#define ASCII \\\n+\t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n+\t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n+\t\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" \\\n+\t\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\" \\\n+\t\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" \\\n+\t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n+\t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n+\t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\"\n\n int cmd__ctype(int argc, const char **argv)\n {\n@@ -38,6 +52,7 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(is_glob_special, \"*?[\\\\\");\n \tTEST_CLASS(is_regex_special, \"$()*+.?[\\\\^{|\");\n \tTEST_CLASS(is_pathspec_magic, \"!\\\"#%&',-/:;<=>@_`~\");\n+\tTEST_CLASS(isascii, ASCII);\n\n \treturn rc;\n }\n--\n2.39.1\n\n"},{"id":"471979","messageId":"bf9ef090-dcd3-e92b-948e-e31ca1243d28@web.de","threadId":"59230","inReplyTo":"06da58d6-6aae-7b1d-6ce6-f07d27f05d97@web.de","subject":"[PATCH 2/3] test-ctype: test islower and isupper","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-11T13:12:52Z","receivedAt":"2023-02-11T13:13:06Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifiers added by 43ccdf56ec (ctype: implement\nislower/isupper macro, 2012-02-10).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex caf586649f..8ac76e93e4 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -53,6 +53,8 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(is_regex_special, \"$()*+.?[\\\\^{|\");\n \tTEST_CLASS(is_pathspec_magic, \"!\\\"#%&',-/:;<=>@_`~\");\n \tTEST_CLASS(isascii, ASCII);\n+\tTEST_CLASS(islower, LOWER);\n+\tTEST_CLASS(isupper, UPPER);\n\n \treturn rc;\n }\n--\n2.39.1\n"},{"id":"471980","messageId":"d1796664-a6e1-1178-d887-46a095daf121@web.de","threadId":"59230","inReplyTo":"06da58d6-6aae-7b1d-6ce6-f07d27f05d97@web.de","subject":"[PATCH 3/3] test-ctype: test iscntrl, ispunct, isxdigit and isprint","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-11T13:12:56Z","receivedAt":"2023-02-11T13:13:08Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifiers added by 1c149ab2dd (ctype: support\niscntrl, ispunct, isxdigit and isprint, 2012-10-15) and 0fcec2ce54\n(format-patch: make rfc2047 encoding more strict, 2012-10-18).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 15 +++++++++++++++\n 1 file changed, 15 insertions(+)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex 8ac76e93e4..d04da0d465 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -42,6 +42,17 @@ static int is_in(const char *s, int ch)\n \t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n \t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n \t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\"\n+#define CNTRL \\\n+\t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n+\t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n+\t\"\\x7f\"\n+#define PRINT \\\n+\t\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" \\\n+\t\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\" \\\n+\t\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" \\\n+\t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n+\t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n+\t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\"\n\n int cmd__ctype(int argc, const char **argv)\n {\n@@ -55,6 +66,10 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(isascii, ASCII);\n \tTEST_CLASS(islower, LOWER);\n \tTEST_CLASS(isupper, UPPER);\n+\tTEST_CLASS(iscntrl, CNTRL);\n+\tTEST_CLASS(ispunct, \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\");\n+\tTEST_CLASS(isxdigit, DIGIT \"abcdefABCDEF\");\n+\tTEST_CLASS(isprint, PRINT);\n\n \treturn rc;\n }\n--\n2.39.1\n"},{"id":"471985","messageId":"xmqqr0uwdlvh.fsf@gitster.g","threadId":"59230","inReplyTo":"21f316ab-714a-58f6-a8d2-466d738b4ed3@web.de","subject":"Re: [PATCH 1/3] test-ctype: test isascii","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-11T19:48:18Z","receivedAt":"2023-02-11T19:48:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <l.s.r@web.de> writes:\n\n> Test the character classifier added by c2e9364a06 (cleanup: add\n> isascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\n> special treatment, as our string-based tester can't find it with\n> strcmp(3).  Allow NUL to be given as the first character in a class\n> specification string.  This has the downside of no longer supporting\n> the empty string, but that's OK since we are not interested in testing\n> character classes with no members.\n\nI wonder how effective a test we can have by checking a table we use\nin production (i.e. ctype.c::sane_ctype[]) against another table we\nuse only for testing (i.e. string literals in test-ctype.c), but\nthat is not something new in this series.\n\nI do not offhand know if the string literal prefixed with NUL is\nsafe against clever compilers; my gut feeling says it should\n(i.e. allowing such an \"optimization\" does not seem to have much\nmerit), but my gut has been wrong many times in this area, so...\n\n>\n> Signed-off-by: René Scharfe <l.s.r@web.de>\n> ---\n>  t/helper/test-ctype.c | 19 +++++++++++++++++--\n>  1 file changed, 17 insertions(+), 2 deletions(-)\n>\n> diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\n> index 92c4c2313e..caf586649f 100644\n> --- a/t/helper/test-ctype.c\n> +++ b/t/helper/test-ctype.c\n> @@ -11,9 +11,14 @@ static void report_error(const char *class, int ch)\n>\n>  static int is_in(const char *s, int ch)\n>  {\n> -\t/* We can't find NUL using strchr.  It's classless anyway. */\n> +\t/*\n> +\t * We can't find NUL using strchr. Accept it as the first\n> +\t * character in the spec -- there are no empty classes.\n> +\t */\n>  \tif (ch == '\\0')\n> -\t\treturn 0;\n> +\t\treturn ch == *s;\n> +\tif (*s == '\\0')\n> +\t\ts++;\n>  \treturn !!strchr(s, ch);\n>  }\n>\n> @@ -28,6 +33,15 @@ static int is_in(const char *s, int ch)\n>  #define DIGIT \"0123456789\"\n>  #define LOWER \"abcdefghijklmnopqrstuvwxyz\"\n>  #define UPPER \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n> +#define ASCII \\\n> +\t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n> +\t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n> +\t\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" \\\n> +\t\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\" \\\n> +\t\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" \\\n> +\t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n> +\t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n> +\t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\"\n>\n>  int cmd__ctype(int argc, const char **argv)\n>  {\n> @@ -38,6 +52,7 @@ int cmd__ctype(int argc, const char **argv)\n>  \tTEST_CLASS(is_glob_special, \"*?[\\\\\");\n>  \tTEST_CLASS(is_regex_special, \"$()*+.?[\\\\^{|\");\n>  \tTEST_CLASS(is_pathspec_magic, \"!\\\"#%&',-/:;<=>@_`~\");\n> +\tTEST_CLASS(isascii, ASCII);\n>\n>  \treturn rc;\n>  }\n> --\n> 2.39.1\n"},{"id":"471990","messageId":"70f4042a-df30-26e5-55bd-b349cc02c416@web.de","threadId":"59230","inReplyTo":"xmqqr0uwdlvh.fsf@gitster.g","subject":"Re: [PATCH 1/3] test-ctype: test isascii","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-12T09:48:12Z","receivedAt":"2023-02-12T09:48:27Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 11.02.23 um 20:48 schrieb Junio C Hamano:\n> René Scharfe <l.s.r@web.de> writes:\n>\n>> Test the character classifier added by c2e9364a06 (cleanup: add\n>> isascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\n>> special treatment, as our string-based tester can't find it with\n>> strcmp(3).  Allow NUL to be given as the first character in a class\n>> specification string.  This has the downside of no longer supporting\n>> the empty string, but that's OK since we are not interested in testing\n>> character classes with no members.\n>\n> I wonder how effective a test we can have by checking a table we use\n> in production (i.e. ctype.c::sane_ctype[]) against another table we\n> use only for testing (i.e. string literals in test-ctype.c), but\n> that is not something new in this series.\n\nWhat aspect is left uncovered?\n\nOr do you mean that the production table should be made trivially\nreadable to avoid having to test at all?\n\nI on the other hand wonder if we really should add more and more\nlocale-ignoring classifiers.  Parsing object headers and such sure\nrequire that stability, but parsing commit messages and blob\npayloads should perhaps better be done with locale-aware versions\nwith multi-byte character support.\n\n> I do not offhand know if the string literal prefixed with NUL is\n> safe against clever compilers; my gut feeling says it should\n> (i.e. allowing such an \"optimization\" does not seem to have much\n> merit), but my gut has been wrong many times in this area, so...\n\nSome compilers do despicable things in the name of optimization, but I\ndon't see the basis for truncating a string literal at the first NUL.\n\nC99 standard section 6.4.5 (String literals) paragraph 5 has a footnote\nthat says: \"A character string literal need not be a string (see 7.1.1),\nbecause a null character may be embedded in it by a \\0 escape sequence.\"\nand 7.1.1 defines: \"A string is a contiguous sequence of characters\nterminated by and including the first null character.\"\n\nRené\n"},{"id":"471998","messageId":"xmqqttzqcjyj.fsf@gitster.g","threadId":"59230","inReplyTo":"70f4042a-df30-26e5-55bd-b349cc02c416@web.de","subject":"Re: [PATCH 1/3] test-ctype: test isascii","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-13T03:39:32Z","receivedAt":"2023-02-13T03:40:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <l.s.r@web.de> writes:\n\n> Am 11.02.23 um 20:48 schrieb Junio C Hamano:\n>> René Scharfe <l.s.r@web.de> writes:\n>>\n>>> Test the character classifier added by c2e9364a06 (cleanup: add\n>>> isascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\n>>> special treatment, as our string-based tester can't find it with\n>>> strcmp(3).  Allow NUL to be given as the first character in a class\n>>> specification string.  This has the downside of no longer supporting\n>>> the empty string, but that's OK since we are not interested in testing\n>>> character classes with no members.\n>>\n>> I wonder how effective a test we can have by checking a table we use\n>> in production (i.e. ctype.c::sane_ctype[]) against another table we\n>> use only for testing (i.e. string literals in test-ctype.c), but\n>> that is not something new in this series.\n>\n> What aspect is left uncovered?\n>\n> Or do you mean that the production table should be made trivially\n> readable to avoid having to test at all?\n\nMuch closer to the latter but not quite.\n\nBoth tables are not all that transparent, and it feels that the\nprotection by the tests largely depends on the fact that it is less\nlikely for us to make the same mistake in two \"not so crystal clear\"\ntables for the same byte.\n\n> ... but parsing commit messages and blob\n> payloads should perhaps better be done with locale-aware versions\n> with multi-byte character support.\n\nYes, that does make sense but it is orthogonal to what sane_ctype\nwants to address, I would think.\n"},{"id":"472022","messageId":"93793a00-da6a-81b4-348f-cd7b946bb9eb@web.de","threadId":"59230","inReplyTo":"xmqqttzqcjyj.fsf@gitster.g","subject":"Re: [PATCH 1/3] test-ctype: test isascii","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-13T18:37:15Z","receivedAt":"2023-02-13T18:37:32Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 13.02.23 um 04:39 schrieb Junio C Hamano:\n> René Scharfe <l.s.r@web.de> writes:\n>\n>> Am 11.02.23 um 20:48 schrieb Junio C Hamano:\n>>> René Scharfe <l.s.r@web.de> writes:\n>>>\n>>>> Test the character classifier added by c2e9364a06 (cleanup: add\n>>>> isascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\n>>>> special treatment, as our string-based tester can't find it with\n>>>> strcmp(3).  Allow NUL to be given as the first character in a class\n>>>> specification string.  This has the downside of no longer supporting\n>>>> the empty string, but that's OK since we are not interested in testing\n>>>> character classes with no members.\n>>>\n>>> I wonder how effective a test we can have by checking a table we use\n>>> in production (i.e. ctype.c::sane_ctype[]) against another table we\n>>> use only for testing (i.e. string literals in test-ctype.c), but\n>>> that is not something new in this series.\n>>\n>> What aspect is left uncovered?\n>>\n>> Or do you mean that the production table should be made trivially\n>> readable to avoid having to test at all?\n>\n> Much closer to the latter but not quite.\n>\n> Both tables are not all that transparent, and it feels that the\n> protection by the tests largely depends on the fact that it is less\n> likely for us to make the same mistake in two \"not so crystal clear\"\n> tables for the same byte.\n\nThe test strings for islower() and isupper() I wrote down from memory\nlong ago, I think.  They should be easily verifiable, like the new ones\nfor isxdigit().  The one for isascii() is a bit tiring, but verifying it\nagainst the man page which says that the characters from value 0 to 0177\nare included should be feasible.  The ones for iscntrl() and ispunct() I\ngot from their man page.\n\nBut when it came to isprint() I got lazy and just copied from ctype.c --\nyou got me there.  A more intuitive representation could be:\n\n   \" \" LOWER UPPER DIGIT PUNCT\n\nIn my experience having two copies already helps when modifying one of\nthem -- but at least at some point we better check them against an\nexternal source of truth.\n\nThe ctype.c version needs to be fast, so we probably have to make some\nconcessions to readability.  I'd love to be proven wrong on that,\nthough.\n\n>> ... but parsing commit messages and blob\n>> payloads should perhaps better be done with locale-aware versions\n>> with multi-byte character support.\n>\n> Yes, that does make sense but it is orthogonal to what sane_ctype\n> wants to address, I would think.\n\nCurrently we can only use one or the other variant because our sane\nversions use the same names as the locale-aware ones.  Full overlap\ninstead of orthogonality.  I don't know if there is a practical impact\nbesides not recognizing function lines that start with umlauts etc.\nfor diff hunk headers, though.\n\nRené\n"},{"id":"472023","messageId":"xmqq3579crsd.fsf@gitster.g","threadId":"59230","inReplyTo":"93793a00-da6a-81b4-348f-cd7b946bb9eb@web.de","subject":"Re: [PATCH 1/3] test-ctype: test isascii","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-13T19:02:42Z","receivedAt":"2023-02-13T19:03:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <l.s.r@web.de> writes:\n\n>> Yes, that does make sense but it is orthogonal to what sane_ctype\n>> wants to address, I would think.\n>\n> Currently we can only use one or the other variant because our sane\n> versions use the same names as the locale-aware ones.  Full overlap\n> instead of orthogonality.\n\nAh, that is true but slightly complicated.  As long as the caller of\nwalks the string byte-by-byte and calls ispunct() in each iteration,\nI do not think any \"locale aware ispunct()\" do much good to us.\n\nOnce callers are made locale aware, I am not sure they would still\nwant to call the isfoo() functions that have been know to be very\nmuch byte-oriented.\n\nThanks.\n\n\n"},{"id":"472029","messageId":"81eee04b-598e-dfe1-f954-3105bcbcb2f2@web.de","threadId":"59230","inReplyTo":"06da58d6-6aae-7b1d-6ce6-f07d27f05d97@web.de","subject":"[PATCH v2 0/3] test-ctype: test all classifiers","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-13T21:08:12Z","receivedAt":"2023-02-13T21:08:25Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add tests to cover the remaining character class test functions.\n\nChanges since v1:\n- More compact and readable isprint() test string specification by\n  reusing the one for ispunct().\n\n  test-ctype: test isascii\n  test-ctype: test islower and isupper\n  test-ctype: test iscntrl, ispunct, isxdigit and isprint\n\n t/helper/test-ctype.c | 30 ++++++++++++++++++++++++++++--\n 1 file changed, 28 insertions(+), 2 deletions(-)\n\nInterdiff against v1:\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex d04da0d465..b21bd672d9 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -33,6 +33,7 @@ static int is_in(const char *s, int ch)\n #define DIGIT \"0123456789\"\n #define LOWER \"abcdefghijklmnopqrstuvwxyz\"\n #define UPPER \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n+#define PUNCT \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\"\n #define ASCII \\\n \t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n \t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n@@ -46,13 +47,6 @@ static int is_in(const char *s, int ch)\n \t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n \t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n \t\"\\x7f\"\n-#define PRINT \\\n-\t\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" \\\n-\t\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\" \\\n-\t\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" \\\n-\t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n-\t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n-\t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\"\n\n int cmd__ctype(int argc, const char **argv)\n {\n@@ -67,9 +61,9 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(islower, LOWER);\n \tTEST_CLASS(isupper, UPPER);\n \tTEST_CLASS(iscntrl, CNTRL);\n-\tTEST_CLASS(ispunct, \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\");\n+\tTEST_CLASS(ispunct, PUNCT);\n \tTEST_CLASS(isxdigit, DIGIT \"abcdefABCDEF\");\n-\tTEST_CLASS(isprint, PRINT);\n+\tTEST_CLASS(isprint, LOWER UPPER DIGIT PUNCT \" \");\n\n \treturn rc;\n }\n\nRange-diff against v1:\n1:  f8a7889fb4 = 1:  f8a7889fb4 test-ctype: test isascii\n2:  1e0c313b38 = 2:  1e0c313b38 test-ctype: test islower and isupper\n3:  dcaffe6917 < -:  ---------- test-ctype: test iscntrl, ispunct, isxdigit and isprint\n-:  ---------- > 3:  cb50e581d4 test-ctype: test iscntrl, ispunct, isxdigit and isprint\n\n--\n2.39.1\n"},{"id":"472030","messageId":"c740cbc6-d9db-88df-b10f-904bdd5e2e06@web.de","threadId":"59230","inReplyTo":"81eee04b-598e-dfe1-f954-3105bcbcb2f2@web.de","subject":"[PATCH v2 1/3] test-ctype: test isascii","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-13T21:09:58Z","receivedAt":"2023-02-13T21:10:11Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifier added by c2e9364a06 (cleanup: add\nisascii(), 2009-03-07).  It returns 1 for NUL as well, which requires\nspecial treatment, as our string-based tester can't find it with\nstrcmp(3).  Allow NUL to be given as the first character in a class\nspecification string.  This has the downside of no longer supporting\nthe empty string, but that's OK since we are not interested in testing\ncharacter classes with no members.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 19 +++++++++++++++++--\n 1 file changed, 17 insertions(+), 2 deletions(-)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex 92c4c2313e..caf586649f 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -11,9 +11,14 @@ static void report_error(const char *class, int ch)\n\n static int is_in(const char *s, int ch)\n {\n-\t/* We can't find NUL using strchr.  It's classless anyway. */\n+\t/*\n+\t * We can't find NUL using strchr. Accept it as the first\n+\t * character in the spec -- there are no empty classes.\n+\t */\n \tif (ch == '\\0')\n-\t\treturn 0;\n+\t\treturn ch == *s;\n+\tif (*s == '\\0')\n+\t\ts++;\n \treturn !!strchr(s, ch);\n }\n\n@@ -28,6 +33,15 @@ static int is_in(const char *s, int ch)\n #define DIGIT \"0123456789\"\n #define LOWER \"abcdefghijklmnopqrstuvwxyz\"\n #define UPPER \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n+#define ASCII \\\n+\t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n+\t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n+\t\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" \\\n+\t\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\" \\\n+\t\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" \\\n+\t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n+\t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n+\t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\"\n\n int cmd__ctype(int argc, const char **argv)\n {\n@@ -38,6 +52,7 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(is_glob_special, \"*?[\\\\\");\n \tTEST_CLASS(is_regex_special, \"$()*+.?[\\\\^{|\");\n \tTEST_CLASS(is_pathspec_magic, \"!\\\"#%&',-/:;<=>@_`~\");\n+\tTEST_CLASS(isascii, ASCII);\n\n \treturn rc;\n }\n--\n2.39.1\n"},{"id":"472031","messageId":"ed877364-51a6-187d-8d37-17e82677c0ff@web.de","threadId":"59230","inReplyTo":"81eee04b-598e-dfe1-f954-3105bcbcb2f2@web.de","subject":"[PATCH v2 2/3] test-ctype: test islower and isupper","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-13T21:10:45Z","receivedAt":"2023-02-13T21:10:57Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifiers added by 43ccdf56ec (ctype: implement\nislower/isupper macro, 2012-02-10).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex caf586649f..8ac76e93e4 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -53,6 +53,8 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(is_regex_special, \"$()*+.?[\\\\^{|\");\n \tTEST_CLASS(is_pathspec_magic, \"!\\\"#%&',-/:;<=>@_`~\");\n \tTEST_CLASS(isascii, ASCII);\n+\tTEST_CLASS(islower, LOWER);\n+\tTEST_CLASS(isupper, UPPER);\n\n \treturn rc;\n }\n--\n2.39.1\n"},{"id":"472032","messageId":"cae75cb9-305b-5ffd-dbb2-8cb83f102541@web.de","threadId":"59230","inReplyTo":"81eee04b-598e-dfe1-f954-3105bcbcb2f2@web.de","subject":"[PATCH v2 3/3] test-ctype: test iscntrl, ispunct, isxdigit and isprint","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2023-02-13T21:12:02Z","receivedAt":"2023-02-13T21:12:19Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Test the character classifiers added by 1c149ab2dd (ctype: support\niscntrl, ispunct, isxdigit and isprint, 2012-10-15) and 0fcec2ce54\n(format-patch: make rfc2047 encoding more strict, 2012-10-18).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-ctype.c | 9 +++++++++\n 1 file changed, 9 insertions(+)\n\ndiff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c\nindex 8ac76e93e4..b21bd672d9 100644\n--- a/t/helper/test-ctype.c\n+++ b/t/helper/test-ctype.c\n@@ -33,6 +33,7 @@ static int is_in(const char *s, int ch)\n #define DIGIT \"0123456789\"\n #define LOWER \"abcdefghijklmnopqrstuvwxyz\"\n #define UPPER \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n+#define PUNCT \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\"\n #define ASCII \\\n \t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n \t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n@@ -42,6 +43,10 @@ static int is_in(const char *s, int ch)\n \t\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\" \\\n \t\"\\x60\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\" \\\n \t\"\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\"\n+#define CNTRL \\\n+\t\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" \\\n+\t\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\" \\\n+\t\"\\x7f\"\n\n int cmd__ctype(int argc, const char **argv)\n {\n@@ -55,6 +60,10 @@ int cmd__ctype(int argc, const char **argv)\n \tTEST_CLASS(isascii, ASCII);\n \tTEST_CLASS(islower, LOWER);\n \tTEST_CLASS(isupper, UPPER);\n+\tTEST_CLASS(iscntrl, CNTRL);\n+\tTEST_CLASS(ispunct, PUNCT);\n+\tTEST_CLASS(isxdigit, DIGIT \"abcdefABCDEF\");\n+\tTEST_CLASS(isprint, LOWER UPPER DIGIT PUNCT \" \");\n\n \treturn rc;\n }\n--\n2.39.1\n"},{"id":"472033","messageId":"xmqqa61h9qhh.fsf@gitster.g","threadId":"59230","inReplyTo":"81eee04b-598e-dfe1-f954-3105bcbcb2f2@web.de","subject":"Re: [PATCH v2 0/3] test-ctype: test all classifiers","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-13T21:59:06Z","receivedAt":"2023-02-13T21:59:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <l.s.r@web.de> writes:\n\n> Add tests to cover the remaining character class test functions.\n>\n> Changes since v1:\n> - More compact and readable isprint() test string specification by\n>   reusing the one for ispunct().\n\nVery nice.  Thanks.\n\n"}]}