Re: gnulib portability issues
Eric Blake ebl...@redhat.com writes: Wrong. Pretty much every libc out there lets you ungetc() more than one byte. Does that include glibc? Then there is a bug in the manual, which says: The GNU C library only supports one character of pushback—in other words, it does not work to call ungetc twice without doing input in between. in the description of ungetc().
Re: musl compatibility
Il 08/06/2012 12:19, Pedro Alves ha scritto: Have you any plans to address these problems? In particular, it does seem odd to place a burden on libc authors of porting gnulib to it, rather than just not supporting those functions which require non-standard APIs on such libc's. I've heard such rants as well. The rants are IMO, misdirected. For instance, IIRC, gnulib's freadahead use is caused by musl's printf not being posix compliant, causing gnulib to pull in its printf replacement, which doesn't work on musl. A library that is new, actively maintained, and that calls itself a C/POSIX standard library should really address that by making it's printf posix compliant, so that gnulib's fallback doesn't even get built. It seems that nobody who is interested in musl has looked at gnulib's config.log to understand why does gnulib think musl's printf is not good enough. While I agree with this, perhaps we can follow the suggestion and replace if (freadahead (f)) with if (freading(f) !feof(f)) in closein.c. Paolo
Re: Why require SLOW_BUT_NO_HACKS for stubs?
Il 12/06/2012 03:22, Isaac Dunham ha scritto: Performance, surely. But if there's consensus that performance does not matter that much with musl, perhaps we should default to the slow version with musl. The test as it stands is error out on unsupported platforms unless user specifies to use slow method. My proposal is On unsupported platforms, use the slow method instead of erroring out. I agree, downgrading to a #warning and removing SLOW_BUT_NO_HACKS should be enough. That would be something like this, but it would fail the tests. What to do? Paolo 8 From e2aa7434ad06a0ec4e2c47b57564313d16561c14 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini pbonz...@redhat.com Date: Tue, 12 Jun 2012 13:26:57 +0200 Subject: [PATCH 1/1] freadahead, freadptr, freadseek: Never fail compilation 2012-06-12 Paolo Bonzini bonz...@gnu.org * lib/freadahead.c [!SLOW_BUT_NO_HACKS]: Use the slow alternative, downgrading the #error to a #warning. * lib/freadptr.c [!SLOW_BUT_NO_HACKS]: Likewise. * lib/freadseek.c [!SLOW_BUT_NO_HACKS]: Likewise. * modules/freadahead: Depend on freading. --- lib/freadahead.c |9 + lib/freadptr.c |5 ++--- lib/freadseek.c|4 ++-- modules/freadahead |1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/freadahead.c b/lib/freadahead.c index 2ba8b34..473911f 100644 --- a/lib/freadahead.c +++ b/lib/freadahead.c @@ -21,6 +21,7 @@ #include stdlib.h #include stdio-impl.h +#include freading.h size_t freadahead (FILE *fp) @@ -84,10 +85,10 @@ freadahead (FILE *fp) if (fp-state == 4 /* WR */ || fp-rp = fp-wp) return 0; return fp-wp - fp-rp; -#elif defined SLOW_BUT_NO_HACKS /* users can define this */ - abort (); - return 0; #else - #error Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib. + /* This implementation is correct on any ANSI C platform. It is just + awfully slow. */ + return freading(fp) !feof(fp); + #warning Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib. #endif } diff --git a/lib/freadptr.c b/lib/freadptr.c index 27c2285..325d91d 100644 --- a/lib/freadptr.c +++ b/lib/freadptr.c @@ -108,11 +108,10 @@ freadptr (FILE *fp, size_t *sizep) return NULL; *sizep = fp-wp - fp-rp; return fp-rp; -#elif defined SLOW_BUT_NO_HACKS /* users can define this */ +#else /* This implementation is correct on any ANSI C platform. It is just awfully slow. */ return NULL; -#else - #error Please port gnulib freadptr.c to your platform! Look at the definition of fflush, fread, getc, getc_unlocked on your system, then report this to bug-gnulib. + #warning Please port gnulib freadptr.c to your platform! Look at the definition of fflush, fread, getc, getc_unlocked on your system, then report this to bug-gnulib. #endif } diff --git a/lib/freadseek.c b/lib/freadseek.c index 4145173..67de1c0 100644 --- a/lib/freadseek.c +++ b/lib/freadseek.c @@ -60,9 +60,9 @@ freadptrinc (FILE *fp, size_t increment) fp-__bufp += increment; #elif defined EPLAN9/* Plan9 */ fp-rp += increment; -#elif defined SLOW_BUT_NO_HACKS /* users can define this */ #else - #error Please port gnulib freadseek.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib. + /* Doing nothing is fine on any ANSI C platform. It is just awfully slow. */ + #warning Please port gnulib freadseek.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib. #endif } diff --git a/modules/freadahead b/modules/freadahead index 96ef2e8..4730695 100644 --- a/modules/freadahead +++ b/modules/freadahead @@ -8,6 +8,7 @@ lib/freadahead.c lib/stdio-impl.h Depends-on: +freading configure.ac: -- 1.7.10.2
Re: Why require SLOW_BUT_NO_HACKS for stubs?
Please don't forget fseterr, the other rude #erroring spot which fails even though there is deactivated portable fallback code. Subject: [PATCH] 6 syscalls is still better than a failed build --- lib/fseterr.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib/fseterr.c b/lib/fseterr.c index eaad702..37efa4f 100644 --- a/lib/fseterr.c +++ b/lib/fseterr.c @@ -45,7 +45,7 @@ fseterr (FILE *fp) fp-_Mode |= 0x200 /* _MERR */; #elif defined __MINT__ /* Atari FreeMiNT */ fp-__error = 1; -#elif 0 /* unknown */ +#elif 1 /* unknown */ /* Portable fallback, based on an idea by Rich Felker. Wow! 6 system calls for something that is just a bit operation! Not activated on any system, because there is no way to repair FP when -- 1.7.3.4
Re: gnulib portability issues
On 06/12/2012 01:04 AM, Ben Pfaff wrote: Eric Blake ebl...@redhat.com writes: Wrong. Pretty much every libc out there lets you ungetc() more than one byte. Does that include glibc? Then there is a bug in the manual, which says: The GNU C library only supports one character of pushback—in other words, it does not work to call ungetc twice without doing input in between. in the description of ungetc(). That's the glibc documentation and I agree it is inaccurate; the Linux man-pages project is better: ungetc() pushes c back to stream, cast to unsigned char, where it is available for subsequent read operations. Pushed-back characters will be returned in reverse order; only one pushback is guaranteed. And this simple program proves that most libc know how to push back more than one byte, whether or not they differ from the original contents, and especially in the common case where the byte still fits in the buffer. It's the corner case where the bytes being pushed back differ from the backing store, and where they don't fit in the normal buffer (perhaps because you have used setvbuf or friends), and therefore libc has to malloc() some pushback storage, and if the malloc fails then so does the ungetc(). $ cat foo.c #include stdio.h int main(void) { char buf[10]; if (fseek(stdin, 0, SEEK_CUR)) return 1; if (fread(buf, 1, sizeof(buf), stdin) != 10) return 2; if (ungetc(buf[9], stdin) != buf[9]) return 3; if (ungetc(buf[8], stdin) != buf[8]) return 4; if (getchar() != buf[8]) return 5; if (getchar() != buf[9]) return 6; if (ungetc(buf[9] + 1, stdin) != buf[9] + 1) return 7; if (ungetc(buf[8] + 1, stdin) != buf[8] + 1) return 8; if (getchar() != buf[8] + 1) return 9; if (getchar() != buf[9] + 1) return 10; return 0; } $ ./foo foo.c; echo $? 0 -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: musl compatibility
On 06/12/2012 05:21 AM, Paolo Bonzini wrote: Il 08/06/2012 12:19, Pedro Alves ha scritto: Have you any plans to address these problems? In particular, it does seem odd to place a burden on libc authors of porting gnulib to it, rather than just not supporting those functions which require non-standard APIs on such libc's. I've heard such rants as well. The rants are IMO, misdirected. For instance, IIRC, gnulib's freadahead use is caused by musl's printf not being posix compliant, causing gnulib to pull in its printf replacement, which doesn't work on musl. A library that is new, actively maintained, and that calls itself a C/POSIX standard library should really address that by making it's printf posix compliant, so that gnulib's fallback doesn't even get built. It seems that nobody who is interested in musl has looked at gnulib's config.log to understand why does gnulib think musl's printf is not good enough. While I agree with this, perhaps we can follow the suggestion and replace if (freadahead (f)) with if (freading(f) !feof(f)) in closein.c. freading() is just as much an extension as freadahead(), but it might be an easier extension to implement. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: gnulib portability issues
On 06/09/2012 06:39 PM, Rich Felker wrote: Hi, Reuben suggested I contact upstream since we've been discussing on the musl mailing list (m...@lists.openwall.com, archive at http://www.openwall.com/lists/musl/) some of the difficulties that have arisen out of gnulib and programs using it when building on musl (http://www.etalabs.net/musl/). I'd like to apologize in advance if some of our users (myself included) have been a bit harsh criticizing gnulib; it's just been a constant source of frustration for us. With that said, here's a summary of some of the issues we've run into: 1. freadahead is inherently non-portable and has no working portable fallback version. At some point in the discussions, it was suggested that this function should not be pulled in except on old broken systems where stdio doesn't work and needs replacement functions. However, at least some packages, notably GNU M4, seem to use it directly. I think we're still discussing this, but hopefully coming to a workable solution for everyone. 2. Several tests for isnanl and printf long double support are invalid. They are generating invalid LD80 representations that cannot occur as values (pseudo-denormal, for example) and testing that isnanl and printf treat these as NAN. Per the C standard, there is no need to handle these bit patterns (attempting to use them as floating point values results in UB); all it does is make isnanl() slightly slower and larger, so I'm reluctant to change our isnanl to match gnulib's expectations. Actually, there IS a need to handle these representations. The 'od' program in coreutils is an example of where POSIX requires us to handle ANY bit pattern as given in an arbitrary input file as ANY other type of number, including long doubles. And that means that all possible bit patterns, even the invalid LD80 representations that cannot occur as a result of arithmetic, CAN occur via memory aliasing, and we really do desire to output those as NaN via the use of isnanl(). 3. The test for POSIX compatible getopt does not actually test for POSIX compatibility, but for GNU semantics which are contrary to POSIX. This is purely an issue of a misnamed test; if gnulib wants to provide a replacement getopt with GNU semantics, that's okay, but it should not tell the user that the host getopt is not POSIX compatible. We've already separated the getopt module into tests for POSIX behavior vs. tests for GNU extension behavior. Which particular aspect are you claiming is incorrectly attributed to POSIX behavior when it should be treated as GNU behavior instead? And is this occurring when the getopt-gnu module is in use, or is it reproducible when using just the getopt-posix module? Or is this just a case of inaccurate wording but accurate testing? 4. Some replacement functions in gnulib have special-cases for each of a set of known-broken systems, with an #else case containing #error. Some of them accept -DSLOW_BUT_NO_HACKS to avoid the error, but it's not clear to me that most of them work, and it seems very undesirable that programs should simply fail to build on unknown systems unless the person running the build is aware of the obscure -DSLOW_BUT_NO_HACKS solution. Wouldn't it be better to include default-case code that works, and possibly issue a #warning that it might perform suboptimally? That seems to be the consensus, and I think this is very much intertwined with the answer to your point 1. Please Cc me and Reuben on responses if that's okay since I'm not subscribed and I believe he might have delivery disabled for this list. It's list policy to reply-to-all anyways, so that only people that set specific 'followup-to' headers get trimmed because they asked to be trimmed. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: [PATCH] maint.mk: fix VPATH issues
Le 11 juin 2012 à 14:11, Jim Meyering a écrit : Hi Akim, You're welcome to use pwd. set -e is in effect, so pwd failure will be caught, and changing the working directory in a script like this is not a problem. Hi Jim! commit b630d56579abda426606c94747748982f30e4a6c Author: Akim Demaille a...@lrde.epita.fr Date: Thu Jun 7 16:17:36 2012 +0200 gnu-web-doc-update: VPATH builds * build-aux/gnu-web-doc-update (--builddir): New option. Revamp the handling of options. Prefer $(...) to `...`. Don't pass --tmpdir=. to mktemp, it is useless given that we specify the template, and it is GNU mktemp specific. Prefer set -e to long series of . Restore the initial git branch, not master. Properly initialize submodules (don't rely only on bootstrap) Do not reconfigure blindly, use config.status. * top/README-release: Update instructions for gnu-web-doc-update. is pushed.
Re: [PATCH] maint.mk: fix VPATH issues
Hi! Le 7 juin 2012 à 18:10, Jim Meyering a écrit : Looks fine. One suggested addition: @@ -67,7 +68,8 @@ These options must be specified: The following are optional: - --news=NEWS_FILE + --news=NEWS_FILE accumulates Telling how to use it, good! How about saying what it is, too? I just installed this. From b42157dd01e3243646f5a8270c09ee125a8aca21 Mon Sep 17 00:00:00 2001 From: Akim Demaille a...@lrde.epita.fr Date: Tue, 12 Jun 2012 12:23:59 +0200 Subject: [PATCH] announce-gen: VPATH issues * build-aux/announce-gen (--srcdir): New option, used to trim the $srcdir part of the path from $builddir to NEWS. * top/maint.mk (announcement): Adjust. --- ChangeLog |7 +++ build-aux/announce-gen | 12 top/maint.mk |1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index ebace5f..ecff180 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-06-12 Akim Demaille a...@lrde.epita.fr + announce-gen: VPATH issues + * build-aux/announce-gen (--srcdir): New option, used to trim the + $srcdir part of the path from $builddir to NEWS. + * top/maint.mk (announcement): Adjust. + +2012-06-12 Akim Demaille a...@lrde.epita.fr + gnu-web-doc-update: VPATH builds * build-aux/gnu-web-doc-update (--builddir): New option. Revamp the handling of options. diff --git a/build-aux/announce-gen b/build-aux/announce-gen index ff581fa..ec7c22a 100755 --- a/build-aux/announce-gen +++ b/build-aux/announce-gen @@ -3,7 +3,7 @@ eval '(exit $?0)' eval 'exec perl -wS $0 ${1+$@}' if 0; # Generate a release announcement message. -my $VERSION = '2012-05-23 08:55'; # UTC +my $VERSION = '2012-06-08 06:53'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook @@ -38,6 +38,7 @@ use POSIX qw(strftime); my %valid_release_types = map {$_ = 1} qw (alpha beta stable); my @archive_suffixes = ('tar.gz', 'tar.bz2', 'tar.lzma', 'tar.xz'); +my $srcdir = '.'; sub usage ($) { @@ -52,7 +53,7 @@ sub usage ($) my @types = sort keys %valid_release_types; print $STREAM EOF; Usage: $ME [OPTIONS] -Generate an announcement message. +Generate an announcement message. Run this from builddir. OPTIONS: @@ -67,7 +68,9 @@ These options must be specified: The following are optional: - --news=NEWS_FILE + --news=NEWS_FILE include the NEWS section about this release +from this NEWS_FILE; accumulates. + --srcdir=DIR where to find the NEWS_FILEs (default: $srcdir) --bootstrap-tools=TOOL_LIST a comma-separated list of tools, e.g., autoconf,automake,bison,gnulib --gnulib-version=VERSION report VERSION as the gnulib version, where @@ -182,7 +185,7 @@ sub print_news_deltas ($$$) my ($news_file, $prev_version, $curr_version) = @_; my $news_name = $news_file; - $news_name =~ s|^\./||; + $news_name =~ s|^\Q$srcdir\E/||; print \n$news_name\n\n; @@ -388,6 +391,7 @@ sub get_tool_versions ($$) 'gpg-key-id=s' = \$gpg_key_id, 'url-directory=s'= \@url_dir_list, 'news=s' = \@news_file, + 'srcdir=s' = \$srcdir, 'bootstrap-tools=s' = \$bootstrap_tools, 'gnulib-version=s' = \$gnulib_version, 'print-checksums!' = \$print_checksums_p, diff --git a/top/maint.mk b/top/maint.mk index f0b889b..7cd24b8 100644 --- a/top/maint.mk +++ b/top/maint.mk @@ -1268,6 +1268,7 @@ announcement: NEWS ChangeLog $(rel-files) --prev=$(PREV_VERSION) \ --curr=$(VERSION) \ --gpg-key-id=$(gpg_key_ID) \ + --srcdir=$(srcdir) \ --news=$(srcdir)/NEWS \ --bootstrap-tools=$(bootstrap-tools)\ $$(case ,$(bootstrap-tools), in (*,gnulib,*)\ -- 1.7.10.4 1
Re: musl compatibility
Il 12/06/2012 14:14, Eric Blake ha scritto: While I agree with this, perhaps we can follow the suggestion and replace if (freadahead (f)) with if (freading(f) !feof(f)) in closein.c. freading() is just as much an extension as freadahead(), but it might be an easier extension to implement. musl has it, too. Paolo
Re: gnulib portability issues
On Tue, Jun 12, 2012 at 06:21:24AM -0600, Eric Blake wrote: 2. Several tests for isnanl and printf long double support are invalid. They are generating invalid LD80 representations that cannot occur as values (pseudo-denormal, for example) and testing that isnanl and printf treat these as NAN. Per the C standard, there is no need to handle these bit patterns (attempting to use them as floating point values results in UB); all it does is make isnanl() slightly slower and larger, so I'm reluctant to change our isnanl to match gnulib's expectations. Actually, there IS a need to handle these representations. The 'od' program in coreutils is an example of where POSIX requires us to handle ANY bit pattern as given in an arbitrary input file as ANY other type of number, including long doubles. And that means that all possible bit patterns, even the invalid LD80 representations that cannot occur as a result of arithmetic, CAN occur via memory aliasing, and we really do desire to output those as NaN via the use of isnanl(). So isnanl is expected to be slower in every program that's using it for legitimate arithmetic purposes for the sake of one program's ease of implementing a non-standard and mostly useless feature? How often have you heard of anybody running od to dump a file of raw LD80 values? If this feature is desired, the test for invalid representations belongs in od itself, where the cost only affects od, not in every single mathematical program. If you were just using gnulib to replace isnanl in od, it wouldn't be such an issue. But considering printf broken, and replacing printf because of this, is a big issue. Replacing printf is non-trivial, and might not even work (for instance if your replacement of printf happens to call some standard library function that the implementation happened to implement in terms of printf, you get infinite recursion). Attempting to replace big functions like printf should be avoided unless absolutely necessary. 3. The test for POSIX compatible getopt does not actually test for POSIX compatibility, but for GNU semantics which are contrary to POSIX. This is purely an issue of a misnamed test; if gnulib wants to provide a replacement getopt with GNU semantics, that's okay, but it should not tell the user that the host getopt is not POSIX compatible. We've already separated the getopt module into tests for POSIX behavior vs. tests for GNU extension behavior. Which particular aspect are you claiming is incorrectly attributed to POSIX behavior when it should be treated as GNU behavior instead? And is this occurring when the getopt-gnu module is in use, or is it reproducible when using just the getopt-posix module? Or is this just a case of inaccurate wording but accurate testing? I was testing with GNU m4. The test that fails has non-option arguments placed before options, and tests to see if it can get the option with getopt. Rich
Re: gnulib portability issues
On 06/12/2012 07:46 AM, Rich Felker wrote: Actually, there IS a need to handle these representations. The 'od' program in coreutils is an example of where POSIX requires us to handle ANY bit pattern as given in an arbitrary input file as ANY other type of number, including long doubles. And that means that all possible bit patterns, even the invalid LD80 representations that cannot occur as a result of arithmetic, CAN occur via memory aliasing, and we really do desire to output those as NaN via the use of isnanl(). So isnanl is expected to be slower in every program that's using it for legitimate arithmetic purposes for the sake of one program's ease of implementing a non-standard and mostly useless feature? How often have you heard of anybody running od to dump a file of raw LD80 values? If this feature is desired, the test for invalid representations belongs in od itself, where the cost only affects od, not in every single mathematical program. If you were just using gnulib to replace isnanl in od, it wouldn't be such an issue. But considering printf broken, and replacing printf because of this, is a big issue. Replacing printf is non-trivial, and might not even work (for instance if your replacement of printf happens to call some standard library function that the implementation happened to implement in terms of printf, you get infinite recursion). Attempting to replace big functions like printf should be avoided unless absolutely necessary. You have a fair argument here, but Bruno needs to weigh in on it since it was his decision to mark printf 'broken' when handed undefined input. I agree with you that printf(%Ld,n) not printing NaN for undefined input is a much different case than isnanl(n) not returning true for out-of-range input. It would indeed be feasible to say that printf() is POSIX compatible if it correctly handles all inputs that are only possible via defined arithmetic, and require that programs like od that translate bit patterns into numbers outside of arithmetic take extra steps to sanitize pseudo-denormals into something that will be printed correctly rather than blindly pass all bit patterns to printf directly. That may still require an isnanl() replacement, but hopefully Bruno would agree that a printf() replacement is overkill. 3. The test for POSIX compatible getopt does not actually test for POSIX compatibility, but for GNU semantics which are contrary to POSIX. This is purely an issue of a misnamed test; if gnulib wants to provide a replacement getopt with GNU semantics, that's okay, but it should not tell the user that the host getopt is not POSIX compatible. We've already separated the getopt module into tests for POSIX behavior vs. tests for GNU extension behavior. Which particular aspect are you claiming is incorrectly attributed to POSIX behavior when it should be treated as GNU behavior instead? And is this occurring when the getopt-gnu module is in use, or is it reproducible when using just the getopt-posix module? Or is this just a case of inaccurate wording but accurate testing? I was testing with GNU m4. The test that fails has non-option arguments placed before options, and tests to see if it can get the option with getopt. GNU m4 requires the GNU extensions to getopt; so this may be a case of just inaccurate wording in the configure output. Also, the last release tarball of m4 (1.4.16, Mar 2011) predates some gnulib improvements to the getopt module, so if that was the version you were testing, it might also be a symptom of something that would be fixed by me doing a refresh release of m4 against newer gnulib. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: gnulib portability issues
On Tue, Jun 12, 2012 at 06:12:39AM -0600, Eric Blake wrote: And this simple program proves that most libc know how to push back more than one byte, whether or not they differ from the original contents, and especially in the common case where the byte still fits in the buffer. It's the corner case where the bytes being pushed back differ from the backing store, and where they don't fit in the normal buffer (perhaps because you have used setvbuf or friends), and therefore libc has to malloc() some pushback storage, and if the malloc fails then so does the ungetc(). This is where we (musl vs glibc and perhaps you) have very different design philosophies. Using a single non-switchable buffer simplifies all the stdio code paths a lot, and reduces the cost of unget/get cycles. I wouldn't look fondly on changing this for the sake of supporting something that the standard says applications can't rely upon. Moreover, our stdio, aside from functions like fopen/fclose that affect the open file list, are intentionally async-signal-safe provided that the same FILE is not used in the signal handler and the interrupted code. Of course the standard doesn't require this, but I think this non-mandated behavior is a lot more useful certain developers (possibly embedded/realtime folks targetting exactly one OS/libc/piece of hardware) than arbitrary-length ungetc. The reason I mention all this is to point out that implementations could just all do X and conform to our expectations is often not as simple as it sounds. Some implementations are just bad, but others have very conscious decisions to do things differently, some of which may be incompatible with the changes you would expect to be easy. Rich
Re: gnulib portability issues
On 06/12/2012 08:03 AM, Rich Felker wrote: On Tue, Jun 12, 2012 at 06:12:39AM -0600, Eric Blake wrote: And this simple program proves that most libc know how to push back more than one byte, whether or not they differ from the original contents, and especially in the common case where the byte still fits in the buffer. It's the corner case where the bytes being pushed back differ from the backing store, and where they don't fit in the normal buffer (perhaps because you have used setvbuf or friends), and therefore libc has to malloc() some pushback storage, and if the malloc fails then so does the ungetc(). This is where we (musl vs glibc and perhaps you) have very different design philosophies. Using a single non-switchable buffer simplifies all the stdio code paths a lot, and reduces the cost of unget/get cycles. I wouldn't look fondly on changing this for the sake of supporting something that the standard says applications can't rely upon. We're talking past each other. I never said that ungetc() should support more than one pushback byte, only that most libc implementations already do support it as an extension. I fully agree with the current standards that say that at most one pushback byte is portable, and GNU m4 goes to great lengths to comply with that. Furthermore, I claim that musl need not go out its way to provide an extension where ungetc can be used for more than one byte. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: gnulib portability issues
On 06/12/2012 08:20 AM, Rich Felker wrote: To me, the only difference is the pain of replacing them. You cannot have these bit patterns in an LD80 without your program having invoked undefined behavior (accessing an object as a type other than its effective type or one of the allowed exceptions), so there's no fundamental reason either should handle it. In fact it's conceivable that machines could exist where even just loading the bit pattern into a floating point register would generate a signal, But isnanl() is required to operate in spite of signaling representations (that is, isnanl() need NOT load a bit pattern into a floating point register). so really od should be performing the test on the unsigned char[] array *before* reinterpreting it to LD80 rather than calling a function that takes an LD80 argument to make the test.. But then you are forcing programs to add #ifdefs and sizeof(long double)==12 checks, instead of letting libc do it for them. That is, testing for an invalid LD80 bit representation is implementation-specific (it depends on the specific hardware and compiler ABI before you even have a long double that can have the invalid representation), but isnanl() is generic - we'd much rather have the generic code do the implementation-specific filtering rather than having to make every client learn the #ifdefs necessary for implementation-specific bit pattern filtering. That said, practicality may win on this one, and you may indeed convince Jim that adding an #ifdef into coreutils' od.c is better than bloating isnanl() for the majority of applications that never convert raw bit patterns into long doubles. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: gnulib portability issues
On Tue, Jun 12, 2012 at 09:07:05AM -0600, Eric Blake wrote: On 06/12/2012 08:20 AM, Rich Felker wrote: To me, the only difference is the pain of replacing them. You cannot have these bit patterns in an LD80 without your program having invoked undefined behavior (accessing an object as a type other than its effective type or one of the allowed exceptions), so there's no fundamental reason either should handle it. In fact it's conceivable that machines could exist where even just loading the bit pattern into a floating point register would generate a signal, But isnanl() is required to operate in spite of signaling representations (that is, isnanl() need NOT load a bit pattern into a floating point register). Signaling nans and trap representations are different things per the standard. A signaling nan is a legitimate value that raises a floating point exception flag (not a signal) when it's used in arithmetic, and which is created in an implementation-defined way, if at all. A trap representation (for any type, not just floating point) is a pattern of bits that results in undefined behavior if it is read by an lvalue expression that does not have character type. so really od should be performing the test on the unsigned char[] array *before* reinterpreting it to LD80 rather than calling a function that takes an LD80 argument to make the test.. But then you are forcing programs to add #ifdefs and sizeof(long double)==12 checks, instead of letting libc do it for them. That is, testing for an invalid LD80 bit representation is implementation-specific (it depends on the specific hardware and compiler ABI before you even have a long double that can have the invalid representation), but isnanl() is generic - we'd much rather have the generic code do the implementation-specific filtering rather than having to make every client learn the #ifdefs necessary for implementation-specific bit pattern filtering. I agree this is ugly. One possible solution would be a function (in gnulib) to inspect a byte array and report whether it's a valid long double representation. That said, practicality may win on this one, and you may indeed convince Jim that adding an #ifdef into coreutils' od.c is better than bloating isnanl() for the majority of applications that never convert raw bit patterns into long doubles. I don't really care if the fix is an ugly bit test in in od.c or a call to isnanl in od.c before the call to printf and letting gnulib's isnanl handle the case; avoiding the printf replacement is enough for me. I do think only approaches that avoid reading the bits as LD80 before they're known to be a non-trap representation can be 100% safe against obscure machines, but on the other hand, avoiding machine-specific code in od.c will probably make the situation better for practical portability. Rich