On 2024-03-12, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
and the answer came back “1037”. The idea that a C-language
implementation and run-time environment is any sense monolithic seems
hopelessly out of touch.
There is no such out-of-touch idea. In (say) a Glibc-based system, only
the GCC, Glibc and kernel headers are part of the implementation (which comprises C, POSIX plus GNU and Linux extensions), and only the GCC and
Glibc library components and their external names.
Other libraries are third parties; the __ and _[A-Z] namespace
simply doesn't belong to them.
C doesn't provide any special tools for the application developer and
third party code to avoid clashes among themselves.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
My specific complaint was about temporary names being used internal to
library macros. It’s a problem that is essentially impossible to solve
with string-based macro processors.
Here's the macro definition you cited upthread:
"""
From /usr/include/«arch»/bits/select.h on my Debian system:
#define __FD_ZERO(s) \
do { \
unsigned int __i; \
fd_set *__arr = (s); \
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
__FDS_BITS (__arr)[__i] = 0; \
} while (0)
"""
Can you explain how that would cause a problem?
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Wed, 13 Mar 2024 22:33:02 GMT, Scott Lurndal wrote:
Third party libraries are allowed to use any mechanism they like to
minimize name conflicts other than prefixing with two underscores.
But there is no other such mechanism available.
Are you aware that working third party libraries exist, and name
collisions are fairly rare? How do you think that's possible?
There are no 100% reliable mechanisms. There are mechanisms that work
well enough in practice, including using library-specific prefixes.
On 2024-03-12, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
From /usr/include/<<arch>>/bits/select.h on my Debian system:
#define __FD_ZERO(s) \
do { \
unsigned int __i; \
fd_set *__arr = (s); \
This assignment has value; it checks that, loosely speaking,
s is an "assignment compatible" pointer with a fd_set *,
so that there is a diagnostic if the macro is applied to
an object of the wrong type.
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
__FDS_BITS (__arr)[__i] = 0; \
Here, I would have done memset(__arr, 0, sizeof *__arr).
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[some editing of white space done]
On 2024-03-12, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
From /usr/include/<<arch>>/bits/select.h on my Debian system:This assignment has value; it checks that, loosely speaking,
#define __FD_ZERO(s) \ >>>>> do { \ >>>>> unsigned int __i; \ >>>>> fd_set *__arr = (s); \ >>>>
s is an "assignment compatible" pointer with a fd_set *,
so that there is a diagnostic if the macro is applied to
an object of the wrong type.
More to the point, if the macro is applied to a value of the wrong
type.
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ >>>>> __FDS_BITS (__arr)[__i] = 0; \ >>>>Here, I would have done memset(__arr, 0, sizeof *__arr).
That assumes that it is the entire fd_set that needs to be zeroed,
which may not be right. Note the call to the __FDS_BITS() macro.
Better:
#define __FD_ZERO(s) ( \ >>> (void) memset( \ >>> __FDS_BITS( (fd_set*){(s)} ), 0, sizeof __FDS_BITS( (fd_set*){0} ) \ >>> ) \ >>> )
This definition: avoids introducing any new identifiers; checks
that the argument s yields an assignment compatible pointer; and
provides a macro that can be used as a void expression (unlike the
original macro definition, which can be used only as a statement).
For context, here's the entire file from my system (Ubuntu 24.0.4,
package libc6-dev:amd64 2.35-0ubuntu3.6). I get the impression that the >>author(s) decided not to use memset to avoid the required #include,
which might increase compilation times for code that indirectly includes >>this header. (I offer no opinion on whether that's a good tradeoff.)
Note that __FD_ZERO is very clearly *not* intended to be invoked by >>arbitrary code.
```
/* Copyright (C) 1997-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _SYS_SELECT_H
# error "Never use <bits/select.h> directly; include <sys/select.h> instead." >>#endif
/* We don't use `memset' because this would require a prototype and
the array isn't too big. */
#define __FD_ZERO(s) \
do { \
unsigned int __i; \ >> fd_set *__arr = (s); \ >> for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ >> __FDS_BITS (__arr)[__i] = 0; \ >> } while (0)
#define __FD_SET(d, s) \
((void) (__FDS_BITS (s)[__FD_ELT(d)] |= __FD_MASK(d)))
#define __FD_CLR(d, s) \
((void) (__FDS_BITS (s)[__FD_ELT(d)] &= ~__FD_MASK(d)))
#define __FD_ISSET(d, s) \
((__FDS_BITS (s)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
```
That code is only selected if it is not compiled with
gcc. If it is gcc 2 or later, the header file uses
# define __FD_ZERO(fdsp) \
do { \
int __d0, __d1; \
__asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS \
: "=c" (__d0), "=D" (__d1) \
: "a" (0), "0" (sizeof (fd_set) \
/ sizeof (__fd_mask)), \
"1" (&__FDS_BITS (fdsp)[0]) \
: "memory"); \
} while (0)
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[some editing of white space done]
On 2024-03-12, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
From /usr/include/<<arch>>/bits/select.h on my Debian system:This assignment has value; it checks that, loosely speaking,
#define __FD_ZERO(s) \ >>>> do { \ >>>> unsigned int __i; \ >>>> fd_set *__arr = (s); \ >>>
s is an "assignment compatible" pointer with a fd_set *,
so that there is a diagnostic if the macro is applied to
an object of the wrong type.
More to the point, if the macro is applied to a value of the wrong
type.
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ >>>> __FDS_BITS (__arr)[__i] = 0; \ >>>Here, I would have done memset(__arr, 0, sizeof *__arr).
That assumes that it is the entire fd_set that needs to be zeroed,
which may not be right. Note the call to the __FDS_BITS() macro.
Better:
#define __FD_ZERO(s) ( \ >> (void) memset( \ >> __FDS_BITS( (fd_set*){(s)} ), 0, sizeof __FDS_BITS( (fd_set*){0} ) \ >> ) \ >> )
This definition: avoids introducing any new identifiers; checks
that the argument s yields an assignment compatible pointer; and
provides a macro that can be used as a void expression (unlike the
original macro definition, which can be used only as a statement).
For context, here's the entire file from my system (Ubuntu 24.0.4,
package libc6-dev:amd64 2.35-0ubuntu3.6). I get the impression that the >author(s) decided not to use memset to avoid the required #include,
which might increase compilation times for code that indirectly includes
this header. (I offer no opinion on whether that's a good tradeoff.)
Note that __FD_ZERO is very clearly *not* intended to be invoked by
arbitrary code.
```
/* Copyright (C) 1997-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _SYS_SELECT_H
# error "Never use <bits/select.h> directly; include <sys/select.h> instead." >#endif
/* We don't use `memset' because this would require a prototype and
the array isn't too big. */
#define __FD_ZERO(s) \
do { \
unsigned int __i; \
fd_set *__arr = (s); \
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
__FDS_BITS (__arr)[__i] = 0; \
} while (0)
#define __FD_SET(d, s) \
((void) (__FDS_BITS (s)[__FD_ELT(d)] |= __FD_MASK(d)))
#define __FD_CLR(d, s) \
((void) (__FDS_BITS (s)[__FD_ELT(d)] &= ~__FD_MASK(d)))
#define __FD_ISSET(d, s) \
((__FDS_BITS (s)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
```
scott@slp53.sl.home (Scott Lurndal) writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:[code snipped]
For context, here's the entire file from my system (Ubuntu 24.0.4, >>>package libc6-dev:amd64 2.35-0ubuntu3.6). I get the impression that the >>>author(s) decided not to use memset to avoid the required #include,
which might increase compilation times for code that indirectly includes >>>this header. (I offer no opinion on whether that's a good tradeoff.)
Note that __FD_ZERO is very clearly *not* intended to be invoked by >>>arbitrary code.
```
```
That code is only selected if it is not compiled with
gcc. If it is gcc 2 or later, the header file uses
# define __FD_ZERO(fdsp) \
do { \
int __d0, __d1; \
__asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS \
: "=c" (__d0), "=D" (__d1) \
: "a" (0), "0" (sizeof (fd_set) \
/ sizeof (__fd_mask)), \
"1" (&__FDS_BITS (fdsp)[0]) \
: "memory"); \
} while (0)
Oh? I don't see that code anywhere in the current glibc sources, in any >older version of bits/select.h, or anywhere under /usr/include on my
system.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
For context, here's the entire file from my system (Ubuntu 24.0.4,[...]
package libc6-dev:amd64 2.35-0ubuntu3.6). I get the impression that the
author(s) decided not to use memset to avoid the required #include,
which might increase compilation times for code that indirectly includes
this header. (I offer no opinion on whether that's a good tradeoff.)
An older version did use memset(). It was changed to use a loop in
1997, with a commit message that included:
"Don't use memset to prevent prototype trouble, use simple loop."
It may have been to avoid problems with pre-ANSI C compilers that didn't >support prototypes. That's still speculation on my part.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[some editing of white space done]
On 2024-03-12, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
From /usr/include/<<arch>>/bits/select.h on my Debian system:This assignment has value; it checks that, loosely speaking,
#define __FD_ZERO(s) \ >>>> do { \ >>>> unsigned int __i; \ >>>> fd_set *__arr = (s); \ >>>
s is an "assignment compatible" pointer with a fd_set *,
so that there is a diagnostic if the macro is applied to
an object of the wrong type.
More to the point, if the macro is applied to a value of the wrong
type.
for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ >>>> __FDS_BITS (__arr)[__i] = 0; \ >>>Here, I would have done memset(__arr, 0, sizeof *__arr).
That assumes that it is the entire fd_set that needs to be zeroed,
which may not be right. Note the call to the __FDS_BITS() macro.
Better:
#define __FD_ZERO(s) ( \ >> (void) memset( \ >> __FDS_BITS( (fd_set*){(s)} ), 0, sizeof __FDS_BITS( (fd_set*){0} ) \ >> ) \ >> )
This definition: avoids introducing any new identifiers; checks
that the argument s yields an assignment compatible pointer; and
provides a macro that can be used as a void expression (unlike the
original macro definition, which can be used only as a statement).
For context, here's the entire file from my system (Ubuntu 24.0.4,
package libc6-dev:amd64 2.35-0ubuntu3.6). I get the impression that the author(s) decided not to use memset to avoid the required #include,
which might increase compilation times for code that indirectly includes
this header. [...]
Any library from outside the implementation cannot use reserved
identifiers without invoking undefined behavior, [...]
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (0 / 16) |
Uptime: | 159:10:25 |
Calls: | 10,384 |
Calls today: | 1 |
Files: | 14,056 |
Messages: | 6,416,491 |