From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 57500 invoked by alias); 25 Feb 2020 03:58:18 -0000 Mailing-List: contact libc-help-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Post: List-Help: , Sender: libc-help-owner@sourceware.org Received: (qmail 57490 invoked by uid 89); 25 Feb 2020 03:58:18 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.1 spammy=oh!, oh, H*f:sk:87v9nvk, H*MI:sk:87v9nvk X-HELO: galex-713.eu Received: from portable.galex-713.eu (HELO galex-713.eu) (89.234.186.82) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 25 Feb 2020 03:58:16 +0000 Received: from gal by galex-713.eu with local (Exim 4.92) (envelope-from ) id 1j6RLu-0000vv-4K; Tue, 25 Feb 2020 04:57:46 +0100 From: Alexandre =?ISO-8859-1?Q?Fran=E7ois?= Garreau To: Florian Weimer Cc: libc-help@sourceware.org Subject: Re: =?UTF-8?B?bWFsbG9j4oCZaW5n?= strcat Date: Tue, 25 Feb 2020 03:58:00 -0000 Message-ID: <1920232.nxOQ8X6Npi@galex-713.eu> In-Reply-To: <87v9nvk7mx.fsf@oldenburg2.str.redhat.com> References: <25950016.Ncol2qhMyO@galex-713.eu> <37682248.6cMLHQH9c6@galex-713.eu> <87v9nvk7mx.fsf@oldenburg2.str.redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" X-IsSubscribed: yes X-SW-Source: 2020-02/txt/msg00047.txt.bz2 Le lundi 24 f=C3=A9vrier 2020, 22:17:10 CET Florian Weimer a =C3=A9crit : > * Alexandre Fran=C3=A7ois Garreau: > > Not any more than the current standard strcat functions, which more or > > less behaves the same (except my macro doesn=E2=80=99t buffer overflow,= and is > > not destructive, but I could as well make a version that is > > destructive as well using realloc that would fail for a statically > > allocated first argument): > > #define astrcat(a, b) strcat (realloc (a, strlen(a) + strlen (b) + 1), > > b) > >=20 > > The most often use is to concatenate two strings at a time anyway, so > > it=E2=80=99s already a big step forward to have a self contained interf= ace, > > rather than always repetitively calling malloc with the same > > arguments and often with strcpy combined=E2=80=A6 >=20 > That doesn't match what I see. After all, without garbage collection, > you can't do this: >=20 > astrcat (astract (a, b), c) >=20 > And multi-concatenations are fairly common: > Ohhh, that explains why there is that standard function not allocating=20 anything=E2=80=A6 because you do the allocation before to use your commonly= user- supplied number of concatenations=E2=80=A6 > >> > But I=E2=80=99m curious, what did C11 change about that? > >>=20 > >> It's possible to use a variadic macro and a compound literal to > >> construct an array in a macro, and pass that (along with the array > >> size) to the actual implementation in a function (whose name would > >> be an implementation detail). > >=20 > > Ohhhh, you mean the function-arg-separators commas would become > > arrays- > > separators commas, like that? > > #define astrcat(...) _astrcat((char *[]) {__VA_ARGS__, NULL}) > > char * > > _astrcat (char *strarray[]) > > { > >=20 > > char * result =3D malloc(1); > > size_t len =3D 1; > > off_t i =3D -1; > > result[0] =3D '\0'; > > while (strarray[++i]) > > result =3D strcat(realloc(result, len +=3D strlen(strarray[i])), > >=20 > > strarray[i]); > >=20 > > return result; > >=20 > > } >=20 > I think I wouldn't use the NULL sentinel for the reasons indicated > (silent truncation after memory allocation or other failure, even under > valgrind), and use >=20 > sizeof ((const char *[]) { __VA_ARGS__ }) / sizeof (const char *) >=20 > to compute the number of arguments, and pass that separately from the > pointer. you mean like that? #define anstrcat(...) \ astrncat(sizeof((char *[]) {__VA_ARGS__}), \ (char *[]) {__VA_ARGS__}) char * anstrcat (size_t n; char *strarray[]) { char * result =3D malloc(1); size_t len =3D 1; result[0] =3D '\0'; for (off_t i =3D 0; i < n; ++i) result =3D strcat(realloc(result, len +=3D strlen(strarray[i])),=20 strarray[i]); return result; } Yet this only works with a macro, and is it really unreasonable to expect=20 not to give NULL args? > >> I don't think this could be done in a portable manner before C11. > >=20 > > Why couldn=E2=80=99t a standard variadic function do? it=E2=80=99s only= longer: > > #define astrcat(...) _astrcat (__VA_ARGS__, NULL) >=20 > Yes, I meant C99. Compound literals and __VA_ARGS__ were added in C99. Oh! that=E2=80=99s way different. Not all C11 is implemented but C99 is, a= faik,=20 right? also since recently, C99 got as distant from now as it is from C=20 creation. > >> > And still, why wasn=E2=80=99t a macro such as the one I presented al= ready > >> > introduced? > >>=20 > >> strdup was only recently added to ISO C, and POSIX is somewhat > >> dormant > >> these days. > >=20 > > but there were already convenient functions before standardizations > > weren=E2=80=99t they? such as the scanf =E2=80=9Cm=E2=80=9D (or =E2=80= =9Ca=E2=80=9D I forgot) conversion > > modifier, or vasprintf=E2=80=A6 right? >=20 > asprintf is still a GNU extension. The m scanf modifier is only in > POSIX. Anyway it is not common for non-standard interfaces to be provided=E2=80=A6= so why=20 not one now? like one of the few I=E2=80=99ve shown?