Add strchrnul()
PATCH 1/2 Add strchrnul()
As suggested by Pierre Habouzit, add strchrnul(). It's a useful GNU extension and can simplify string parser code. There are several places in git that can be converted to strchrnul(); as a trivial example, this patch introduces its usage to builtin-fetch--tool.c.
---
Makefile | 13 +++++++++++++ builtin-fetch--tool.c | 8 ++------ compat/strchrnul.c | 8 ++++++++ git-compat-util.h | 5 +++++ 4 files changed, 28 insertions(+), 6 deletions(-)
Makefile +13 -0
@@ -30,6 +30,8 @@ all:: # # Define NO_MEMMEM if you don't have memmem. # +# Define NO_STRCHRNUL if you don't have strchrnul. +# # Define NO_STRLCPY if you don't have strlcpy. # # Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@@ -406,6 +408,7 @@ ifeq ($(uname_S),Darwin) OLD_ICONV = UnfortunatelyYes NO_STRLCPY = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease endif ifeq ($(uname_S),SunOS) NEEDS_SOCKET = YesPlease
@@ -413,6 +416,7 @@ ifeq ($(uname_S),SunOS) SHELL_PATH = /bin/bash NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_HSTRERROR = YesPlease ifeq ($(uname_R),5.8) NEEDS_LIBICONV = YesPlease
@@ -438,6 +442,7 @@ ifeq ($(uname_O),Cygwin) NO_D_INO_IN_DIRENT = YesPlease NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_SYMLINK_HEAD = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -452,12 +457,14 @@ endif ifeq ($(uname_S),FreeBSD) NEEDS_LIBICONV = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib endif ifeq ($(uname_S),OpenBSD) NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib
@@ -473,6 +480,7 @@ endif ifeq ($(uname_S),AIX) NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NEEDS_LIBICONV=YesPlease endif
@@ -485,6 +493,7 @@ ifeq ($(uname_S),IRIX64) NO_SETENV=YesPlease NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NO_SOCKADDR_STORAGE=YesPlease SHELL_PATH=/usr/gnu/bin/bash
@@ -695,6 +704,10 @@ ifdef NO_MEMMEM COMPAT_CFLAGS += -DNO_MEMMEM COMPAT_OBJS += compat/memmem.o endif +ifdef NO_STRCHRNUL + COMPAT_CFLAGS += -DNO_STRCHRNUL + COMPAT_OBJS += compat/strchrnul.o +endif ifdef THREADED_DELTA_SEARCH BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
builtin-fetch--tool.c +2 -6
@@ -435,9 +435,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu cp++;if (!*cp)break ; - np =strchr (cp,'\n' ); -if (!np) - np = cp +strlen (cp); + np =strchrnul (cp,'\n' );if (pass) { lrr_list[i].line = cp; lrr_list[i].name = cp +41 ;
@@ -461,9 +459,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu rref++;if (!*rref)break ; - next =strchr (rref,'\n' ); -if (!next) - next = rref +strlen (rref); + next =strchrnul (rref,'\n' ); rreflen = next - rref;for (i =0 ; i < lrr_count; i++) {
compat/strchrnul.c new file +8 -0
@@ -0,0 +1,8 @@ +#include "../git-compat-util.h" + +char *gitstrchrnul (const char *s,int c) +{ +while (*s && *s != c) + s++; +return (char *)s; +}
git-compat-util.h +5 -0
@@ -183,6 +183,11 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif +#ifdef NO_STRCHRNUL +#define strchrnul gitstrchrnul +char *gitstrchrnul (const char *s,int c); +#endif +extern void release_pack_memory (size_t ,int );static inline char *xstrdup (const char *str)
Quoted 4 lines · René Scharfe
As suggested by Pierre Habouzit, add
strchrnul(). It's a useful GNU extension and can simplify string parser code. There are several places in git that can be converted tostrchrnul(); as a trivial example, this patch introduces its usage tobuiltin-fetch--tool.c.
Minor nit: a comment (in the code or even in the commit message) describing the what the function does would be nice. On a GNU system, one can look at the man page, but on others there is no indication of what it does except for reading the code (and maybe the answer is "this is a common library function, you idiot", but I am familiar with many GNU extensions and didn't know this one).
-Peff
Quoted 19 lines · René Scharfe
As suggested by Pierre Habouzit, add
strchrnul(). It's a useful GNU extension and can simplify string parser code. There are several places in git that can be converted tostrchrnul(); as a trivial example, this patch introduces its usage tobuiltin-fetch--tool.c.Signed-off-by Rene Scharfe <[email protected]>---
Makefile | 13 +++++++++++++ builtin-fetch--tool.c | 8 ++------ compat/strchrnul.c | 8 ++++++++ git-compat-util.h | 5 +++++ 4 files changed, 28 insertions(+), 6 deletions(-)Makefile +0
-0
Makefile all:: · line 34
Quoted 5 lines
Makefile +2
-0@@ -30,6 +30,8 @@ all:: # # Define NO_MEMMEM if you don't have memmem. # +# Define NO_STRCHRNUL if you don't have strchrnul. +#
This seems overly complicated. How about this instead?
From: Andreas Ericsson <[email protected]>
Subject: [PATCH] Add strchrnul()
As suggested by Pierre Habouzit, add strchrnul(). It's a useful GNU extension and can simplify string parser code. There are several places in git that can be converted to strchrnul(); as a trivial example, this patch introduces its usage to builtin-fetch--tool.c.
strchrnul() was introduced in glibc in April 1999 and included in glibc-2.1. Checking for that version means the majority of all git users would get to use the optimized version in glibc. Of the remaining few some might get to use a slightly slower version than necessary but probably not slower than what we have today.
Original patch by Rene Scharfe <[email protected]>
---
I'm fairly much against forcing people to know what library functions they have in order to get software to compile properly. This is, imo, a neater solution, and also inlines the function as suggested by Dscho.
git-compat-util.h +0 -0
@@ -105,6 +105,18 @@ extern void set_die_routine(void (*routine)(const char *err
extern void set_error_routine(void (*routine)(const char *err, va_list params)) extern void set_warn_routine(void (*routine)(const char *warn, va_list params))
+
+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1) +# define strchrnul(s, c) gitstrchrnul(s, c) +static inline char *gitstrchrnul(const char *s, int c) +{
+ while (*s && *s != c)
+ s++;
+
+ return (char *)s;
+}
+#endif
+
#ifdef NO_MMAP
#ifndef PROT_READ
builtin-fetch--tool.c +0 -0
@@ -435,9 +435,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu
cp++;
if (!*cp)
break;
- np = strchr(cp, '\n');
- if (!np)
- np = cp + strlen(cp);
+ np = strchrnul(cp, '\n');
if (pass) {
lrr_list[i].line = cp;
lrr_list[i].name = cp + 41;
@@ -461,9 +459,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu
rref++;
if (!*rref)
break;
- next = strchr(rref, '\n');
- if (!next)
- next = rref + strlen(rref);
+ next = strchrnul(rref, '\n');
rreflen = next - rref;
for (i = 0; i < lrr_count; i++) {Signature · 3 lines
Andreas Ericsson [email protected] OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231
PATCH 1/1 Simplify strchrnul() compat code
From: Andreas Ericsson <[email protected]>
strchrnul() was introduced in glibc in April 1999 and included in glibc-2.1. Checking for that version means the majority of all git users would get to use the optimized version in glibc. Of the remaining few some might get to use a slightly slower version than necessary but probably not slower than what we have today.
---
I agree that we can do without providing a way to use a native version outside glibc until we actually encounter such a thing.
Makefile | 13 ------------- compat/strchrnul.c | 8 -------- git-compat-util.h | 9 +++++++-- 3 files changed, 7 insertions(+), 23 deletions(-)
Makefile +0 -13
@@ -30,8 +30,6 @@ all:: # # Define NO_MEMMEM if you don't have memmem. # -# Define NO_STRCHRNUL if you don't have strchrnul. -# # Define NO_STRLCPY if you don't have strlcpy. # # Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@@ -409,7 +407,6 @@ ifeq ($(uname_S),Darwin) OLD_ICONV = UnfortunatelyYes NO_STRLCPY = YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease endif ifeq ($(uname_S),SunOS) NEEDS_SOCKET = YesPlease
@@ -417,7 +414,6 @@ ifeq ($(uname_S),SunOS) SHELL_PATH = /bin/bash NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease NO_HSTRERROR = YesPlease ifeq ($(uname_R),5.8) NEEDS_LIBICONV = YesPlease
@@ -443,7 +439,6 @@ ifeq ($(uname_O),Cygwin) NO_D_INO_IN_DIRENT = YesPlease NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease NO_SYMLINK_HEAD = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -458,14 +453,12 @@ endif ifeq ($(uname_S),FreeBSD) NEEDS_LIBICONV = YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib endif ifeq ($(uname_S),OpenBSD) NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib
@@ -481,7 +474,6 @@ endif ifeq ($(uname_S),AIX) NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NEEDS_LIBICONV=YesPlease endif
@@ -494,7 +486,6 @@ ifeq ($(uname_S),IRIX64) NO_SETENV=YesPlease NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease - NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NO_SOCKADDR_STORAGE=YesPlease SHELL_PATH=/usr/gnu/bin/bash
@@ -705,10 +696,6 @@ ifdef NO_MEMMEM COMPAT_CFLAGS += -DNO_MEMMEM COMPAT_OBJS += compat/memmem.o endif -ifdef NO_STRCHRNUL - COMPAT_CFLAGS += -DNO_STRCHRNUL - COMPAT_OBJS += compat/strchrnul.o -endif ifdef THREADED_DELTA_SEARCH BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
compat/strchrnul.c deleted +0 -8
@@ -1,8 +0,0 @@ -#include "../git-compat-util.h" - -char *gitstrchrnul (const char *s,int c) -{ -while (*s && *s != c) - s++; -return (char *)s; -}
git-compat-util.h +7 -2
@@ -183,9 +183,14 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#ifdef NO_STRCHRNUL +#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 )#define strchrnul gitstrchrnul -char *gitstrchrnul (const char *s,int c); +static inline char *gitstrchrnul (const char *s,int c) +{ +while (*s && *s != c) + s++; +return (char *)s; +}#endif extern void release_pack_memory (size_t ,int );
Re: [PATCH] Simplify strchrnul() compat code
git-compat-util.h void *gitmemmem(const void *haystack, size_t haystacklen, · line 186
Quoted 3 lines · René Scharfe
git-compat-util.h +1
-1-#ifdef NO_STRCHRNUL +#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 )
This will break things for users of glibc-2.1.1 (the first release still available from ftp://sources.redhat.com/pub/glibc/old-releases that includes the strchrnul() function), since __GLIBC_PREREQ() was invented after strchrnul() was introduced.
Replacing __GLIBC__ with __GLIBC_PREREQ (as in the original patch) will solve it nicely. Users of glibc-2.1.1 will be the odd minority where strchrnul() is available in their libc but not used.
Signature · 3 lines
Andreas Ericsson [email protected] OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231
Re: [PATCH] Simplify strchrnul() compat code
Quoted 4 lines · Andreas Ericsson
Quoted 2 lines · René Scharfe
-#ifdef
NO_STRCHRNUL
+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1)
Quoted 8 lines
This will break things for users of glibc-2.1.1 (the first release still available from ftp://sources.redhat.com/pub/glibc/old-releases that includes the
strchrnul()function), since__GLIBC_PREREQ()was invented afterstrchrnul()was introduced.Replacing
__GLIBC__with__GLIBC_PREREQ(as in the original patch) will solve it nicely. Users of glibc-2.1.1 will be the odd minority wherestrchrnul()is available in their libc but not used.
Do you mean this on top of René's patch? Although I do not think I saw "the original patch" that did it this way, I think it makes sense.
git-compat-util.h +1 -1
@@ -183,7 +183,7 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 ) +#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 )#define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {
Re: [PATCH] Simplify strchrnul() compat code
Quoted 10 lines · Junio C Hamano
Quoted 8 lines · Andreas Ericsson
Quoted 2 lines · René Scharfe
-#ifdef
NO_STRCHRNUL
+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1)This will break things for users of glibc-2.1.1 (the first release still available from ftp://sources.redhat.com/pub/glibc/old-releases that includes the
strchrnul()function), since__GLIBC_PREREQ()was invented afterstrchrnul()was introduced.
Quoted 5 lines
Quoted 3 lines
Replacing
__GLIBC__with__GLIBC_PREREQ(as in the original patch) will solve it nicely. Users of glibc-2.1.1 will be the odd minority wherestrchrnul()is available in their libc but not used.Do you mean this on top of René's patch?
Yes.
Quoted 2 lines
Although I do not
think I saw "the original patch" that did it this way,
My memory seems to be failing. I never committed my proposal to my repo, and the one I sent out was the __GLIBC__ || !__GLIBC_PREREQ thing. My apologies.
Signature · 3 lines
Andreas Ericsson [email protected] OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231
Re: [PATCH] Simplify strchrnul() compat code
In reply to Junio C HamanoQuoted 24 lines · Junio C Hamano
Quoted 4 lines · Andreas Ericsson
Quoted 2 lines · René Scharfe
-#ifdef
NO_STRCHRNUL
+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1)Quoted 8 lines
This will break things for users of glibc-2.1.1 (the first release still available from ftp://sources.redhat.com/pub/glibc/old-releases that includes the
strchrnul()function), since__GLIBC_PREREQ()was invented afterstrchrnul()was introduced.Replacing
__GLIBC__with__GLIBC_PREREQ(as in the original patch) will solve it nicely. Users of glibc-2.1.1 will be the odd minority wherestrchrnul()is available in their libc but not used.Do you mean this on top of René's patch? Although I do not think I saw "the original patch" that did it this way, I think it makes sense.
git-compat-util.h +0
-0
git-compat-util.h void *gitmemmem(const void *haystack, size_t haystacklen, · line 189
Quoted 8 lines
git-compat-util.h +1
-1@@ -183,7 +183,7 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 ) +#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 )#define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {
I just tested it on my machine (OS X Tiger) now that it's in 'next', and this breaks the build:
CC git.o
In file included from builtin.h:4,
from git.c:1:
git-compat-util.h:187:48: error: missing binary operator before token "("
make: *** [git.o] Error 1
I don't think I have __GLIBC_PREREQ defined anywhere I can find.
Dave.
Re: [PATCH] Simplify strchrnul() compat code
Quoted 14 lines · David Symonds
git-compat-util.h void *gitmemmem(const void *haystack, size_t haystacklen, · line 189
Quoted 9 lines · Junio C Hamano
git-compat-util.h +1
-1@@ -183,7 +183,7 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 ) +#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 )#define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {I just tested it on my machine (OS X Tiger) now that it's in 'next', and this breaks the build:
Quoted 8 lines
CC git.o
In file included from builtin.h:4,from git.c:1:git-compat-util.h:187:48: error: missing binary operator before token "("
make: *** [git.o] Error 1I don't think I have
__GLIBC_PREREQdefined anywhere I can find.
Turn the && in that line into || and it should work.
-- Hannes
Re: [PATCH] Simplify strchrnul() compat code
Quoted 22 lines · Johannes Sixt
Quoted 21 lines · David Symonds
git-compat-util.h void *gitmemmem(const void *haystack, size_t haystacklen, · line 189
Quoted 9 lines · Junio C Hamano
git-compat-util.h +1
-1@@ -183,7 +183,7 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC__) && !__GLIBC_PREREQ (2 ,1 ) +#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 )#define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {I just tested it on my machine (OS X Tiger) now that it's in 'next', and this breaks the build:
CC git.o
In file included from builtin.h:4,from git.c:1:git-compat-util.h:187:48: error: missing binary operator before token "("
make: *** [git.o] Error 1
Quoted 3 lines
Quoted 1 line
I don't think I have
__GLIBC_PREREQdefined anywhere I can find.Turn the && in that line into || and it should work.
Nope, no dice. Plus, that'd change the logic. I also tried turning the (!X && !Y) into (X || Y) to no avail.
Dave.
Re: [PATCH] Simplify strchrnul() compat code
Quoted 7 lines · David Symonds
Quoted 3 lines · Johannes Sixt
Quoted 1 line · David Symonds
I don't think I have
__GLIBC_PREREQdefined anywhere I can find.Turn the && in that line into || and it should work.
Nope, no dice. Plus, that'd change the logic. I also tried turning the (!X && !Y) into (X || Y) to no avail.
Ok, then how about this?
---
git-compat-util.h +7 -1
@@ -184,7 +184,13 @@ void *gitmemmem(const void *haystack, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 ) +#ifdef __GLIBC_PREREQ +#if __GLIBC_PREREQ (2 ,1 ) +#define HAVE_STRCHRNUL +#endif +#endif + +#ifndef HAVE_STRCHRNUL #define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {
Re: [PATCH] Simplify strchrnul() compat code
Quoted 31 lines · Johannes Sixt
Quoted 7 lines · David Symonds
Quoted 3 lines · Johannes Sixt
Quoted 1 line · David Symonds
I don't think I have
__GLIBC_PREREQdefined anywhere I can find.Turn the && in that line into || and it should work.
Nope, no dice. Plus, that'd change the logic. I also tried turning the (!X && !Y) into (X || Y) to no avail.
Ok, then how about this?
---
git-compat-util.h +7
-1@@ -184,7 +184,13 @@ void *gitmemmem(const void *haystack, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 ) +#ifdef __GLIBC_PREREQ +#if __GLIBC_PREREQ (2 ,1 ) +#define HAVE_STRCHRNUL +#endif +#endif + +#ifndef HAVE_STRCHRNUL #define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c)
Quoted 1 line
{Yep, that works just fine. Ack.
Dave.
PATCH 1/1 Fix preprocessor logic that determines the availablity of strchrnul().
Apart from the error in the condition (&& should actually be ||), the construct
#if !defined(A) || !A
leads to a syntax error in the C preprocessor if A is indeed not defined.
--- git-compat-util.h | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
git-compat-util.h +7 -1
@@ -184,7 +184,13 @@ void *gitmemmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);#endif -#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 ) +#ifdef __GLIBC_PREREQ +#if __GLIBC_PREREQ (2 ,1 ) +#define HAVE_STRCHRNUL +#endif +#endif + +#ifndef HAVE_STRCHRNUL #define strchrnul gitstrchrnulstatic inline char *gitstrchrnul (const char *s,int c) {
Signature · 1 line
1.5.3.5.578.g1f8ec
Re: [PATCH] Simplify strchrnul() compat code
In reply to David SymondsQuoted 11 lines · David Symonds
Quoted 9 lines · Johannes Sixt
git-compat-util.h +7
-1-#if !defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ (2 ,1 ) +#ifdef __GLIBC_PREREQ +#if __GLIBC_PREREQ (2 ,1 ) +#define HAVE_STRCHRNUL +#endif +#endif + +#ifndef HAVE_STRCHRNUL
Quoted 5 lines
Quoted 3 lines
#define strchrnul gitstrchrnul static inline char *gitstrchrnul(const char *s, int c) {Yep, that works just fine. Ack.
This version has also the following advantage that you can set HAVE_STRCHRNULL if above test does not detect it in your library.
Althought you'd better write then:
+#if __GLIBC_PREREQ(2, 1) && !defined(HAVE_STRCHRNUL)
Ack.
Signature · 3 lines
Jakub Narebski Warsaw, Poland ShadeHawk on #git
[Cc: Andreas Ericsson <[email protected]>,
René Scharfe <[email protected]>,
Junio C Hamano <[email protected]>,
[email protected]]
Quoted 15 lines · Andreas Ericsson
Quoted 14 lines · René Scharfe
As suggested by Pierre Habouzit, add
strchrnul(). It's a useful GNU extension and can simplify string parser code. There are several places in git that can be converted tostrchrnul(); as a trivial example, this patch introduces its usage tobuiltin-fetch--tool.c.Signed-off-by Rene Scharfe <[email protected]>---
Makefile | 13 +++++++++++++ builtin-fetch--tool.c | 8 ++------ compat/strchrnul.c | 8 ++++++++ git-compat-util.h | 5 +++++ 4 files changed, 28 insertions(+), 6 deletions(-)
Quoted 10 lines
Makefile all:: · line 34
Quoted 10 lines
Makefile +2
-0@@ -30,6 +30,8 @@ all:: # # Define NO_MEMMEM if you don't have memmem. # +# Define NO_STRCHRNUL if you don't have strchrnul. +#
Original patch lacked adding appropriate test to configure, i.e. something like below to configure.ac
#
# Define NO_STRCHRNUL if you don't have strchrnul. AC_CHECK_FUNC(strchrnul,
[NO_STRCHRNUL=],
[NO_STRCHRNUL=YesPlease]) AC_SUBST(NO_STRCHRNUL)
and the following line to config.mak.in
NO_STRCHRNUL=@NO_STRCHRNUL@
Quoted 1 line
This seems overly complicated. How about this instead?
[...]
Quoted 4 lines
I'm fairly much against forcing people to know what library functions they have in order to get software to compile properly. This is, imo, a neater solution, and also inlines the function as suggested by Dscho.
Wouldn't it be better to add ./configure check instead? See above.
Although I guess that people using ./configure to set compilation options (to generate config.mak.autogen) are minority...
Review
Quoted 11 lines
(quoted diff) +11
-0+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1) +# define strchrnul(s, c) gitstrchrnul(s, c) +static inline char *gitstrchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + + return (char *)s; +} +#endif +
This is good solution, although I'm not sure about the check itself. What if somebody has libc which is not glibc, but it does have strchrnul?
Quoted 16 lines
builtin-fetch--tool.c +1
-3@@ -435,9 +435,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu cp++;if (!*cp)break ; - np =strchr (cp,'\n' ); -if (!np) - np = cp +strlen (cp); + np =strchrnul (cp,'\n' );if (pass) { lrr_list[i].line = cp; lrr_list[i].name = cp +41 ;
builtin-fetch--tool.c static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu · line 465
Quoted 10 lines
builtin-fetch--tool.c +1
-3@@ -461,9 +459,7 @@ static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_resu rref++;if (!*rref)break ; - next =strchr (rref,'\n' ); -if (!next) - next = rref +strlen (rref); + next =strchrnul (rref,'\n' ); rreflen = next - rref;for (i =0 ; i < lrr_count; i++) {
This IMHO should go to separate patch.
Signature · 3 lines
Jakub Narebski Warsaw, Poland ShadeHawk on #git
Quoted 5 lines · Jakub Narebski
[Cc: Andreas Ericsson <[email protected]>,
René Scharfe <[email protected]>,
Junio C Hamano <[email protected]>,
[email protected]]
I'm not sure what's up with this, but I didn't see this email on git@vger, so re-adding it to the Cc list now.
Quoted 22 lines
Original patch lacked adding appropriate test to configure, i.e. something like below to configure.ac
#
# DefineNO_STRCHRNULif you don't have strchrnul. AC_CHECK_FUNC(strchrnul,
[NO_STRCHRNUL=],
[NO_STRCHRNUL=YesPlease])AC_SUBST(NO_STRCHRNUL)and the following line to config.mak.in
NO_STRCHRNUL=@NO_STRCHRNUL@
Quoted 1 line
This seems overly complicated. How about this instead?
[...]
Quoted 4 lines
I'm fairly much against forcing people to know what library functions they have in order to get software to compile properly. This is, imo, a neater solution, and also inlines the function as suggested by Dscho.
Quoted 5 lines
Wouldn't it be better to add ./configure check instead? See above.
Although I guess that people using ./configure to set compilation options (to generate config.mak.autogen) are minority...
Perhaps. I know I don't anyway, and now it's become standard not to do so for a significant part of the git-tracking world.
Quoted 7 lines
Quoted 7 lines
(quoted diff) +7
-0+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1) +# define strchrnul(s, c) gitstrchrnul(s, c) +static inline char *gitstrchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; +
Quoted 9 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+ return (char *)s; +} +#endif +This is good solution, although I'm not sure about the check itself. What if somebody has libc which is not glibc, but it does have strchrnul?
They most likely fall into the minority that get to suffer from using code that's as fast as what's in there today, although a bit more readable. The glibc optimization is really only worthwhile for architectures where strchrnul()-like operations have microcode support, or when it's used on large strings.
YMMV. I suppose rewriting it as
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 1)
# define HAVE_STRCHRNUL #endif
#ifdef HAVE_STRCHRNUL
...
would work too, and will provide an easier way out for other fellas wanting to say "Hey, my favourite solaris libc has this too!". OTOH, that rewrite can be done when the first such case appears.
Quoted 4 lines
builtin-fetch--tool.c
Quoted 1 line
builtin-fetch--tool.c +0
-0This IMHO should go to separate patch.
*shrug* Rene had it in his. Monkey see monkey do ;-)
Signature · 3 lines
Andreas Ericsson [email protected] OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231
Quoted 19 lines · Andreas Ericsson
Quoted 17 lines · Jakub Narebski
Review
Quoted 11 lines · René Scharfe
(quoted diff) +11
-0+#if !defined(__GLIBC__) && !__GLIBC_PREREQ(2, 1) +# define strchrnul(s, c) gitstrchrnul(s, c) +static inline char *gitstrchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + + return (char *)s; +} +#endif +This is good solution, although I'm not sure about the check itself. What if somebody has libc which is not glibc, but it does have strchrnul?
Quoted 5 lines
They most likely fall into the minority that get to suffer from using code that's as fast as what's in there today, although a bit more readable. The glibc optimization is really only worthwhile for architectures where strchrnul()-like operations have microcode support, or when it's used on large strings.
If we end up using this solution, then adding test for strchrnul in the configure (configure.ac and config.mak.in) is not needed...
Quoted 3 lines
YMMV. I suppose rewriting it as
#if
defined(__GLIBC_PREREQ)&&__GLIBC_PREREQ(2, 1)
#if !defined(HAVE_STRCHRNUL) && \
defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 1)Quoted 9 lines
# define HAVE_STRCHRNUL #endif#ifdef
HAVE_STRCHRNUL
...would work too, and will provide an easier way out for other fellas wanting to say "Hey, my favourite solaris libc has this too!". OTOH, that rewrite can be done when the first such case appears.
...but if we end up using this version (be it HAVE_STRCHRNUL, or NO_STRCHRNUL), then test for strchrnul in ./configure is I think necessary.
Signature · 2 lines
Jakub Narebski Poland
Hi,
Quoted 61 lines · Ren? Scharfe
Makefile +8
-0@@ -30,6 +30,8 @@ all:: # # Define NO_MEMMEM if you don't have memmem. # +# Define NO_STRCHRNUL if you don't have strchrnul. +# # Define NO_STRLCPY if you don't have strlcpy. # # Define NO_STRTOUMAX if you don't have strtoumax in the C library.@@ -406,6 +408,7 @@ ifeq ($(uname_S),Darwin) OLD_ICONV = UnfortunatelyYes NO_STRLCPY = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease endif ifeq ($(uname_S),SunOS) NEEDS_SOCKET = YesPlease@@ -413,6 +416,7 @@ ifeq ($(uname_S),SunOS) SHELL_PATH = /bin/bash NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_HSTRERROR = YesPlease ifeq ($(uname_R),5.8) NEEDS_LIBICONV = YesPlease@@ -438,6 +442,7 @@ ifeq ($(uname_O),Cygwin) NO_D_INO_IN_DIRENT = YesPlease NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_SYMLINK_HEAD = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes@@ -452,12 +457,14 @@ endif ifeq ($(uname_S),FreeBSD) NEEDS_LIBICONV = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib endif ifeq ($(uname_S),OpenBSD) NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib@@ -473,6 +480,7 @@ endif ifeq ($(uname_S),AIX) NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NEEDS_LIBICONV=YesPlease endif
Makefile ifeq ($(uname_S),IRIX64) · line 499
Quoted 7 lines
Makefile +1
-0@@ -485,6 +493,7 @@ ifeq ($(uname_S),IRIX64) NO_SETENV=YesPlease NO_STRCASESTR=YesPlease NO_MEMMEM = YesPlease + NO_STRCHRNUL = YesPlease NO_STRLCPY = YesPlease NO_SOCKADDR_STORAGE=YesPlease SHELL_PATH=/usr/gnu/bin/bash
Might be easier to define HAVE_STRCHRNUL ;-)
Quoted 6 lines
compat/strchrnul.c new file +0
-0
compat/strchrnul.c line 8
Quoted 8 lines
compat/strchrnul.c new file +8
-0@@ -0,0 +1,8 @@ +#include "../git-compat-util.h" + +char *gitstrchrnul (const char *s,int c) +{ +while (*s && *s != c) + s++; +return (char *)s; +}
This is so short, I think it is even better to inline it.
Ciao,
Dscho