Re: BSD m4 (was: more m4 underquotations)
> > I DO know that in the > > current source code of BSD m4, "changequote(,)" behaves > > like "changequote" (ie. sets the quotes to ` and ') rather than > > the GNU behavior of disabling quotes. > > This sounds like a POSIX [1] violation of BSD m4. Nope. It was at my request that the Austin group agreed that POSIX was ambiguous in this area, and that the next version of POSIX will be worded as follows[1]: The behavior is unspecified if there is a single argument or either argument is null. [1]http://www.opengroup.org/austin/aardvark/latest/xcubug2.txt, search for "Enhancement Request Number 112" -- Eric Blake
[PATCH] Add !HAVE_MBRTOWC fallbacks for mbchar, mbiter and mbuiter
Hello, I'm adding multibyte character support to the info viewer using the mbiter and mbuiter modules. Those modules currently depend on mbrtowc () and friends. The mbs* functions in gnulib currently have two separate implementations of most algorithms, one for HAVE_MBRTOWC using mbchar, and one for !HAVE_MBRTOWC. To avoid duplicating the large amount of text-processing code in the info viewer in a similar way, the attached patches add a !HAVE_MBRTOWC implementation of the mbiter, mbuiter and mbchar interfaces. * lib/mbchar.h: #include for ptrdiff_t. * lib/mbchar.h * lib/mbiter.h * lib/mbuiter.h: Add an implementation for !HAVE_MBRTOWC. * m4/mbchar.m4: Require gl_FUNC_MBRTOWC. * m4/mbiter.m4: Remove an obsolete comment. * modules/mbchar: Include m4/mbrtowc.m4. * modules/mbiter * modules/mbuiter: Don't suggest #if HAVE_MBRTOWC around header #includes. Thanks, Mirek Index: lib/mbchar.h === RCS file: /sources/gnulib/gnulib/lib/mbchar.h,v retrieving revision 1.10 diff -u -r1.10 mbchar.h --- lib/mbchar.h 27 Dec 2006 19:54:25 - 1.10 +++ lib/mbchar.h 14 Feb 2007 16:59:55 - @@ -146,8 +146,15 @@ #define _MBCHAR_H 1 #include +#include #include +/* Multibyte characters could in principle be handled without mbrtowc (), but + all current users of mbchar (mbfile, mbiter and mbuiter) need mbrtowc (), + so their !HAVE_MBRTOWC fallbacks need a non-multibyte mbchar + implementation. */ +#if HAVE_MBRTOWC + /* Tru64 with Desktop Toolkit C has a bug: must be included before . BSD/OS 4.1 has a bug: and must be included before @@ -274,6 +281,110 @@ new_mbc->wc = old_mbc->wc; } +#else /* not HAVE_MBRTOWC */ + +#include + +struct mbchar +{ + const char *ptr; /* pointer to current character */ + bool c_valid; /* true if c is a valid character */ + unsigned char c; /* if c_valid: the current character */ + char buf[1]; /* room for the character, used for file input only */ +}; + +/* EOF (not a real character) is represented with c_valid = false. */ + +typedef struct mbchar mbchar_t; + +/* Access the current character. */ +#define mb_ptr(mbc) ((mbc).ptr) +#define mb_len(mbc) ((mbc).c_valid ? 1 : 0) + +/* Comparison of characters. */ +#define mb_iseq(mbc, sc) ((mbc).c_valid && (mbc).c == (sc)) +#define mb_isnul(mbc) ((mbc).c_valid && (mbc).c == 0) +#define mb_cmp(mbc1, mbc2) \ + ((mbc1).c_valid \ + ? ((mbc2).c_valid \ + ? (int) (mbc1).c - (int) (mbc2).c \ + : -1)\ + : ((mbc2).c_valid \ + ? 1\ + : 0)) +#define mb_casecmp(mbc1, mbc2) \ + ((mbc1).c_valid \ + ? ((mbc2).c_valid \ + ? ((int) (unsigned char) tolower ((mbc1).c) \ + - (int) (unsigned char) tolower ((mbc2).c)) \ + : -1)\ + : ((mbc2).c_valid \ + ? 1\ + : 0)) +#define mb_equal(mbc1, mbc2) \ + ((mbc1).c_valid && (mbc2).c_valid \ + ? (mbc1).c == (mbc2).c \ + : !(mbc1).c_valid && !(mbc2).c_valid) +#define mb_caseequal(mbc1, mbc2) \ + ((mbc1).c_valid && (mbc2).c_valid \ + ? tolower ((mbc1).c) == tolower ((mbc2).c)\ + : !(mbc1).c_valid && !(mbc2).c_valid) + +/* , classification. */ +#define mb_isascii(mbc) ((mbc).c_valid && (mbc).c <= 127) +#define mb_isalnum(mbc) ((mbc).c_valid && isalnum ((mbc).c)) +#define mb_isalpha(mbc) ((mbc).c_valid && isalpha ((mbc).c)) +#define mb_isblank(mbc) ((mbc).c_valid && isblank ((mbc).c)) +#define mb_iscntrl(mbc) ((mbc).c_valid && iscntrl ((mbc).c)) +#define mb_isdigit(mbc) ((mbc).c_valid && isdigit ((mbc).c)) +#define mb_isgraph(mbc) ((mbc).c_valid && isgraph ((mbc).c)) +#define mb_islower(mbc) ((mbc).c_valid && islower ((mbc).c)) +#define mb_isprint(mbc) ((mbc).c_valid && isprint ((mbc).c)) +#define mb_ispunct(mbc) ((mbc).c_valid && ispunct ((mbc).c)) +#define mb_isspace(mbc) ((mbc).c_valid && isspace ((mbc).c)) +#define mb_isupper(mbc) ((mbc).c_valid && isupper ((mbc).c)) +#define mb_isxdigit(mbc) ((mbc).c_valid && isxdigit ((mbc).c)) + +/* Extra function. */ + +/* Unprintable characters appear as a small box of width 1. */ +#define MB_UNPRINTABLE_WIDTH 1 + +static inline int +mb_width_aux (int c) +{ + /* For unprintable characters, arbitrarily return 0 for control characters + and MB_UNPRINTABLE_WIDTH otherwise. */ + return isprint (c) ? 1 : iscntrl (c) ? 0 : MB_UNPRINTABLE_WIDTH; +} + +#define mb_width(mbc) \ + ((mbc).c_valid ? mb_width_aux ((mbc).c) : MB_UNPRINTABLE_WIDTH) + +/* Output. */ +#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, mb_len (mbc), (stream)) + +/* Assignment. */ +#define mb_setascii(mbc, sc) \ + ((mbc)->ptr = (mbc)->buf, (mbc)->c_valid = 1, \ + (mbc)->c = (mbc)->buf[0] = (sc)) + +/* Copying a character. */ +static inline void +mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc) +{ + if (old_mbc->ptr == &old_mbc->buf[0]) +{ + new_mbc
Re: check for C99-compliant snprintf
Paul Eggert <[EMAIL PROTECTED]> writes: > It's a bit of a pain that this will reject all cross-compiled snprintfs. > Is there some way you can test for this at compile-time? > > Does the nonstandard snprintf have exactly the same signature as the > C99 snprintf? If not, we should be able to catch this at > compile-time. > > Does the nonstandard implementation have a vsnprintf? If not, we > could test for that at link-time and cross-compiles wouldn't have to > substitute snprintf except on clearly pre-C99 systems. > > Basically, I'm looking for any way we can distinguish the nonstandard > implementation without running it. I agree that it would be nicer to distinguish the non-C99 snprintf at compile time. Unfortunately, the noncompliant snprintf has exactly the same signature and return value, and the system also has vsnprintf. We could of course test whether the system is Windows, using #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ or similar. Is that a better idea? -- Ben Pfaff [EMAIL PROTECTED] http://benpfaff.org
Re: check for C99-compliant snprintf
Ben Pfaff <[EMAIL PROTECTED]> writes: > We could of course test whether the system is Windows, using > #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ > or similar. Is that a better idea? Do you mean to have two Autoconf tests, one at compile-time (with the above code), and one at run-time (with the code proposed earlier)? I.e., do the run-time test only if the compile-time test indicates that there may be trouble. That sounds a bit fancy, but it would work. Or, you could just do the compile-time test and assume the bug exists if it fails. That should be good enough, too.
Re: fix inadequate Windows implementation of tmpfile
Bruno Haible <[EMAIL PROTECTED]> writes: > Paul, what's your opinion on this? Should gnulib includes overrides under > the same function name, even if they contradict the respective platform's > documentation? I think gnulib is for porting GNU applications, and if GNU applications assume glibc behavior for a function then it's OK to replace a vendor's function that behaves differrently.
Re: check for C99-compliant snprintf
Paul Eggert <[EMAIL PROTECTED]> writes: > Ben Pfaff <[EMAIL PROTECTED]> writes: > >> We could of course test whether the system is Windows, using >> #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ >> or similar. Is that a better idea? > > Do you mean to have two Autoconf tests, one at compile-time (with the > above code), and one at run-time (with the code proposed earlier)? > I.e., do the run-time test only if the compile-time test indicates > that there may be trouble. That sounds a bit fancy, but it would > work. > > Or, you could just do the compile-time test and assume the bug exists > if it fails. That should be good enough, too. The latter was what I had in mind. I've appended a revised patch below, which takes that approach. To avoid duplicating the test across snprintf and vsnprintf, I put the test into a separate macro that is AC_REQUIREd. This version works well for snprintf in my original test environment, where I was using --disable-nls. But then when I tested it along with libintl, I noticed that snprintf broke again. I traced it to the following in libintl.h: #undef snprintf #define snprintf libintl_snprintf where libintl_snprintf is a wrapper around the system snprintf, which is still of course broken. I'm not sure how to work around this problem. I guess I could submit a patch against the gettext implementation of libintl_[v]snprintf to fix the problem, and then recommend that mingw users of PSPP either --disable-nls or use the fixed version. Does that sound like an effective solution? vsnprintf is problematic even with --disable-nls, because mingw contains: __CRT_INLINE int __cdecl vsnprintf (char* s, size_t n, const char* format, __VALIST arg) { return _vsnprintf ( s, n, format, arg); } When vsnprintf expands to rpl_vsnprintf, this turns rpl_vsnprintf into a wrapper around the broken _vsnprintf. I chose to fix that by also replacing _vsnprintf, as shown in the patch below. This is all a little gross, and I don't know whether the method I used is acceptable; please let me know. Index: lib/_vsnprintf.c === RCS file: lib/_vsnprintf.c diff -N lib/_vsnprintf.c --- /dev/null 1 Jan 1970 00:00:00 - +++ lib/_vsnprintf.c17 Feb 2007 00:56:08 - @@ -0,0 +1,19 @@ +/* Formatted output to strings. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#define VSNPRINTF _vsnprintf +#include "vsnprintf.c" Index: lib/vasnprintf.c === RCS file: /sources/gnulib/gnulib/lib/vasnprintf.c,v retrieving revision 1.22 diff -u -p -r1.22 vasnprintf.c --- lib/vasnprintf.c30 Jan 2007 01:07:22 - 1.22 +++ lib/vasnprintf.c17 Feb 2007 00:56:09 - @@ -27,6 +27,9 @@ # include #endif +/* If we're replacing snprintf with rpl_snprintf, avoid a loop. */ +#undef snprintf + /* Specification. */ #if WIDE_CHAR_VERSION # include "vasnwprintf.h" Index: lib/vsnprintf.c === RCS file: /sources/gnulib/gnulib/lib/vsnprintf.c,v retrieving revision 1.3 diff -u -p -r1.3 vsnprintf.c --- lib/vsnprintf.c 28 Aug 2006 16:04:14 - 1.3 +++ lib/vsnprintf.c 17 Feb 2007 00:56:09 - @@ -37,13 +37,17 @@ # define EOVERFLOW E2BIG #endif +#ifndef VSNPRINTF +# define VSNPRINTF vsnprintf +#endif + /* Print formatted output to string STR. Similar to vsprintf, but additional length SIZE limit how much is written into STR. Returns string length of formatted string (which may be larger than SIZE). STR may be NULL, in which case nothing will be written. On error, return a negative value. */ int -vsnprintf (char *str, size_t size, const char *format, va_list args) +VSNPRINTF (char *str, size_t size, const char *format, va_list args) { char *output; size_t len; Index: m4/native-w32.m4 === RCS file: m4/native-w32.m4 diff -N m4/native-w32.m4 --- /dev/null 1 Jan 1970 00:00:00 - +++ m4/native-w32.m417 Feb 2007 00:56:09 - @@ -0,0 +1,21 @@ +#serial 1 -*- autoconf -*- + +# Helper macro to detect native w32; that is, a Windows environment +# without
Re: [PATCH] Add !HAVE_MBRTOWC fallbacks for mbchar, mbiter and mbuiter
Eric Blake wrote: > > There are probably two uses of the mbchar, mbfile, mbiter, mbuiter modules: > > (a) Use them only for MB_CUR_MAX > 1, and use simpler datatypes (just > > 'char' and pointers) for MB_CUR_MAX = 1. > > (b) Use them always. > > ... there are things to be aware of. ... > the code didn't consistently stick with approach a) vs. b). The macros I posted can often formulate the algorithm in such a way that it can be instantiated twice: once for MB_CUR_MAX > 1, once for MB_CUR_MAX = 1, _without_ code changes. In other words, if you write /* Instantiate the code for MB_CUR_MAX > 1. */ #include "mbchar_multi.h" #include "my-code.h" #include "mbchar_undef.h" /* Instantiate the code for MB_CUR_MAX = 1. */ #include "mbchar_8bit.h" #include "my-code.h" #include "mbchar_undef.h" you get a multibyte version and a unibyte version of the code that are consistent - because they share the same source code. Bruno