bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: C locale *printf functions ?


From: Ben Pfaff
Subject: Re: C locale *printf functions ?
Date: Mon, 10 Dec 2012 10:34:07 -0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.4 (gnu/linux)

Right, I'll work on those.

What is vsnformat?

John Darrington <address@hidden> writes:

> I gave it a rudimentary test and it seems to do what I want.
> I will also need other related functions, though, Eg xasprintf,
> vsnformat, etc.
>
> J'
>
> On Thu, Dec 06, 2012 at 10:59:44PM -0800, Ben Pfaff wrote:
>      John Darrington <address@hidden> writes:
>      
>      > Gnulib has a number of c-* variants of string processing functions,
>      > eg c-strtod, c-strcasecmp etc  But notably absent are any locale
>      > independent printf routines.   We could use some in PSPP.
>      
>      Here's some initial work on that.  It only defines c_snprintf()
>      so far.  The test passes for me.
>      
>      Comments are welcome, from anyone.
>      
>      ---
>       lib/c-snprintf.c         |   74 
> ++++++++++++++++++++++++++++++++++++++++++++
>       lib/c-snprintf.h         |   46 ++++++++++++++++++++++++++++
>       lib/c-vasnprintf.c       |   43 ++++++++++++++++++++++++++
>       lib/c-vasnprintf.h       |   76 
> ++++++++++++++++++++++++++++++++++++++++++++++
>       modules/c-snprintf       |   23 ++++++++++++++
>       modules/c-snprintf-tests |   17 +++++++++++
>       modules/c-vasnprintf     |   55 +++++++++++++++++++++++++++++++++
>       tests/test-c-snprintf.c  |   58 +++++++++++++++++++++++++++++++++++
>       tests/test-c-snprintf.sh |   15 +++++++++
>       9 files changed, 407 insertions(+)
>       create mode 100644 lib/c-snprintf.c
>       create mode 100644 lib/c-snprintf.h
>       create mode 100644 lib/c-vasnprintf.c
>       create mode 100644 lib/c-vasnprintf.h
>       create mode 100644 modules/c-snprintf
>       create mode 100644 modules/c-snprintf-tests
>       create mode 100644 modules/c-vasnprintf
>       create mode 100644 tests/test-c-snprintf.c
>       create mode 100755 tests/test-c-snprintf.sh
>      
>      diff --git a/lib/c-snprintf.c b/lib/c-snprintf.c
>      new file mode 100644
>      index 0000000..2dadbfc
>      --- /dev/null
>      +++ b/lib/c-snprintf.c
>      @@ -0,0 +1,74 @@
>      +/* Formatted output to strings in C locale.
>      +   Copyright (C) 2004, 2006-2012 Free Software Foundation, Inc.
>      +   Written by Simon Josefsson, Paul Eggert, and Ben Pfaff.
>      +
>      +   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 3, 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, see <http://www.gnu.org/licenses/>.  */
>      +
>      +#include <config.h>
>      +
>      +/* Specification.  */
>      +#include <stdio.h>
>      +
>      +#include <errno.h>
>      +#include <limits.h>
>      +#include <stdarg.h>
>      +#include <stdlib.h>
>      +#include <string.h>
>      +
>      +#include "c-vasnprintf.h"
>      +
>      +/* Print formatted output to string STR.  Similar to sprintf, 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.
>      +
>      +   Formatting takes place in the C locale, that is, the decimal point
>      +   used in floating-point formatting directives is always '.'. */
>      +int
>      +c_snprintf (char *str, size_t size, const char *format, ...)
>      +{
>      +  char *output;
>      +  size_t len;
>      +  size_t lenbuf = size;
>      +  va_list args;
>      +
>      +  va_start (args, format);
>      +  output = c_vasnprintf (str, &lenbuf, format, args);
>      +  len = lenbuf;
>      +  va_end (args);
>      +
>      +  if (!output)
>      +    return -1;
>      +
>      +  if (output != str)
>      +    {
>      +      if (size)
>      +        {
>      +          size_t pruned_len = (len < size ? len : size - 1);
>      +          memcpy (str, output, pruned_len);
>      +          str[pruned_len] = '\0';
>      +        }
>      +
>      +      free (output);
>      +    }
>      +
>      +  if (INT_MAX < len)
>      +    {
>      +      errno = EOVERFLOW;
>      +      return -1;
>      +    }
>      +
>      +  return len;
>      +}
>      diff --git a/lib/c-snprintf.h b/lib/c-snprintf.h
>      new file mode 100644
>      index 0000000..3192a2d
>      --- /dev/null
>      +++ b/lib/c-snprintf.h
>      @@ -0,0 +1,46 @@
>      +/* vsprintf with automatic memory allocation in C locale.
>      +   Copyright (C) 2002-2004, 2007-2012 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 3, 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, see <http://www.gnu.org/licenses/>.  */
>      +
>      +#ifndef _C_SNPRINTF_H
>      +#define _C_SNPRINTF_H
>      +
>      +/* Get size_t.  */
>      +#include <stddef.h>
>      +
>      +/* The __attribute__ feature is available in gcc versions 2.5 and later.
>      +   The __-protected variants of the attributes 'format' and 'printf' are
>      +   accepted by gcc versions 2.6.4 (effectively 2.7) and later.
>      +   We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, 
> because
>      +   gnulib and libintl do '#define printf __printf__' when they override
>      +   the 'printf' function.  */
>      +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
>      +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
>      +#else
>      +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
>      +#endif
>      +
>      +#ifdef __cplusplus
>      +extern "C" {
>      +#endif
>      +
>      +int c_snprintf (char *str, size_t size, const char *format, ...)
>      +       _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4));
>      +
>      +#ifdef __cplusplus
>      +}
>      +#endif
>      +
>      +#endif /* _C_SNPRINTF_H */
>      diff --git a/lib/c-vasnprintf.c b/lib/c-vasnprintf.c
>      new file mode 100644
>      index 0000000..af6ca08
>      --- /dev/null
>      +++ b/lib/c-vasnprintf.c
>      @@ -0,0 +1,43 @@
>      +/* Formatted output to strings in C locale.
>      +   Copyright (C) 2009-2012 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 3 of the License, 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, see 
> <http://www.gnu.org/licenses/>.  */
>      +
>      +#include <config.h>
>      +
>      +#include <string.h>
>      +
>      +#include "printf-parse.h"
>      +
>      +#define VASNPRINTF c_vasnprintf
>      +#define FCHAR_T char
>      +#define DCHAR_T char
>      +#define DIRECTIVE char_directive
>      +#define DIRECTIVES char_directives
>      +#define PRINTF_PARSE printf_parse
>      +#define DCHAR_CPY memcpy
>      +#define DCHAR_SET memset
>      +#define DCHAR_IS_TCHAR 1
>      +#define TCHAR_T char
>      +
>      +#define NEED_PRINTF_DOUBLE 1
>      +#define NEED_PRINTF_LONG_DOUBLE 1 
>      +#define decimal_point_char_defined 1
>      +static char
>      +decimal_point_char (void)
>      +{
>      +  return '.';
>      +}
>      +
>      +#include "vasnprintf.c"
>      diff --git a/lib/c-vasnprintf.h b/lib/c-vasnprintf.h
>      new file mode 100644
>      index 0000000..8fc1724
>      --- /dev/null
>      +++ b/lib/c-vasnprintf.h
>      @@ -0,0 +1,76 @@
>      +/* vsprintf with automatic memory allocation in C locale.
>      +   Copyright (C) 2002-2004, 2007-2012 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 3, 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, see <http://www.gnu.org/licenses/>.  */
>      +
>      +#ifndef _C_VASNPRINTF_H
>      +#define _C_VASNPRINTF_H
>      +
>      +/* Get va_list.  */
>      +#include <stdarg.h>
>      +
>      +/* Get size_t.  */
>      +#include <stddef.h>
>      +
>      +/* The __attribute__ feature is available in gcc versions 2.5 and later.
>      +   The __-protected variants of the attributes 'format' and 'printf' are
>      +   accepted by gcc versions 2.6.4 (effectively 2.7) and later.
>      +   We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, 
> because
>      +   gnulib and libintl do '#define printf __printf__' when they override
>      +   the 'printf' function.  */
>      +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
>      +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
>      +#else
>      +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
>      +#endif
>      +
>      +#ifdef __cplusplus
>      +extern "C" {
>      +#endif
>      +
>      +/* Write formatted output to a string dynamically allocated with 
> malloc().
>      +   You can pass a preallocated buffer for the result in RESULTBUF and 
> its
>      +   size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
>      +   If successful, return the address of the string (this may be = 
> RESULTBUF
>      +   if no dynamic memory allocation was necessary) and set *LENGTHP to 
> the
>      +   number of resulting bytes, excluding the trailing NUL.  Upon error, 
> set
>      +   errno and return NULL.
>      +
>      +   When dynamic memory allocation occurs, the preallocated buffer is 
> left
>      +   alone (with possibly modified contents).  This makes it possible to 
> use
>      +   a statically allocated or stack-allocated buffer, like this:
>      +
>      +          char buf[100];
>      +          size_t len = sizeof (buf);
>      +          char *output = vasnprintf (buf, &len, format, args);
>      +          if (output == NULL)
>      +            ... error handling ...;
>      +          else
>      +            {
>      +              ... use the output string ...;
>      +              if (output != buf)
>      +                free (output);
>      +            }
>      +
>      +   Formatting takes place in the C locale, that is, the decimal point 
> used in
>      +   floating-point formatting directives is always '.'.
>      +  */
>      +extern char *c_vasnprintf (char *resultbuf, size_t *lengthp, const char 
> *format, va_list args)
>      +       _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0));
>      +
>      +#ifdef __cplusplus
>      +}
>      +#endif
>      +
>      +#endif /* _C_VASNPRINTF_H */
>      diff --git a/modules/c-snprintf b/modules/c-snprintf
>      new file mode 100644
>      index 0000000..edebe2b
>      --- /dev/null
>      +++ b/modules/c-snprintf
>      @@ -0,0 +1,23 @@
>      +Description:
>      +c_snprintf(): print formatted output to a fixed length string in C 
> locale
>      +
>      +Files:
>      +lib/c-snprintf.h
>      +lib/c-snprintf.c
>      +
>      +Depends-on:
>      +c-vasnprintf
>      +
>      +configure.ac:
>      +
>      +Makefile.am:
>      +lib_SOURCES += c-snprintf.c
>      +
>      +Include:
>      +"c-snprintf.h"
>      +
>      +License:
>      +GPL
>      +
>      +Maintainer:
>      +Ben Pfaff
>      diff --git a/modules/c-snprintf-tests b/modules/c-snprintf-tests
>      new file mode 100644
>      index 0000000..86d6a14
>      --- /dev/null
>      +++ b/modules/c-snprintf-tests
>      @@ -0,0 +1,17 @@
>      +Files:
>      +tests/test-c-snprintf.c
>      +tests/test-c-snprintf.sh
>      +m4/locale-fr.m4
>      +tests/macros.h
>      +
>      +Depends-on:
>      +setlocale
>      +snprintf
>      +
>      +configure.ac:
>      +gt_LOCALE_FR
>      +
>      +Makefile.am:
>      +TESTS += test-c-snprintf.sh
>      +check_PROGRAMS += test-c-snprintf
>      +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@'
>      diff --git a/modules/c-vasnprintf b/modules/c-vasnprintf
>      new file mode 100644
>      index 0000000..cd94193
>      --- /dev/null
>      +++ b/modules/c-vasnprintf
>      @@ -0,0 +1,55 @@
>      +Description:
>      +Formatted output to strings in C locale.
>      +
>      +Files:
>      +lib/c-vasnprintf.h
>      +lib/c-vasnprintf.c
>      +lib/float+.h
>      +lib/printf-args.h
>      +lib/printf-args.c
>      +lib/printf-parse.h
>      +lib/printf-parse.c
>      +lib/vasnprintf.h
>      +lib/vasnprintf.c
>      +m4/wchar_t.m4
>      +m4/wint_t.m4
>      +m4/longlong.m4
>      +m4/intmax_t.m4
>      +m4/stdint_h.m4
>      +m4/inttypes_h.m4
>      +m4/vasnprintf.m4
>      +m4/printf.m4
>      +m4/math_h.m4
>      +m4/exponentd.m4
>      +
>      +Depends-on:
>      +isnand-nolibm
>      +isnanl-nolibm
>      +frexpl-nolibm
>      +printf-frexp
>      +printf-frexpl
>      +signbit
>      +fpucw
>      +nocrash
>      +printf-safe
>      +alloca-opt
>      +xsize
>      +errno
>      +memchr
>      +multiarch
>      +verify
>      +
>      +configure.ac:
>      +gl_PREREQ_VASNPRINTF_WITH_EXTRAS
>      +
>      +Makefile.am:
>      +lib_SOURCES += c-vasnprintf.c
>      +
>      +Include:
>      +"c-vasnprintf.h"
>      +
>      +License:
>      +GPL
>      +
>      +Maintainer:
>      +Ben Pfaff
>      diff --git a/tests/test-c-snprintf.c b/tests/test-c-snprintf.c
>      new file mode 100644
>      index 0000000..9da5443
>      --- /dev/null
>      +++ b/tests/test-c-snprintf.c
>      @@ -0,0 +1,58 @@
>      +/* Test of snprintf() function.
>      +   Copyright (C) 2011-2012 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 3 of the License, 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, see 
> <http://www.gnu.org/licenses/>.  */
>      +
>      +#include <config.h>
>      +
>      +#include "c-snprintf.h"
>      +
>      +#include <locale.h>
>      +#include <stdio.h>
>      +#include <string.h>
>      +
>      +#include "macros.h"
>      +
>      +int
>      +main (int argc, char *argv[])
>      +{
>      +  /* configure should already have checked that the locale is 
> supported.  */
>      +  if (setlocale (LC_ALL, "") == NULL)
>      +    return 1;
>      +
>      +  /* Test behaviour of snprintf() as a "control group".
>      +     (We should be running in a locale where ',' is the decimal point.) 
> */
>      +  {
>      +    char s[16];
>      +
>      +    snprintf (s, sizeof s, "%#.0f", 1.0);
>      +    if (!strcmp (s, "1."))
>      +      {
>      +        /* Skip the test, since we're not in a useful locale for 
> testing. */
>      +        return 77;
>      +      }
>      +    ASSERT (!strcmp (s, "1,"));
>      +  }
>      +
>      +  /* Test behaviour of c_snprintf().
>      +     It should always use '.' as the decimal point. */
>      +  {
>      +    char s[16];
>      +
>      +    c_snprintf (s, sizeof s, "%#.0f", 1.0);
>      +    ASSERT (!strcmp (s, "1."));
>      +  }
>      +
>      +  return 0;
>      +}
>      diff --git a/tests/test-c-snprintf.sh b/tests/test-c-snprintf.sh
>      new file mode 100755
>      index 0000000..83051fc
>      --- /dev/null
>      +++ b/tests/test-c-snprintf.sh
>      @@ -0,0 +1,15 @@
>      +#!/bin/sh
>      +
>      +# Test in an ISO-8859-1 or ISO-8859-15 locale.
>      +: ${LOCALE_FR=fr_FR}
>      +if test $LOCALE_FR = none; then
>      +  if test -f /usr/bin/localedef; then
>      +    echo "Skipping test: no traditional french locale is installed"
>      +  else
>      +    echo "Skipping test: no traditional french locale is supported"
>      +  fi
>      +  exit 77
>      +fi
>      +
>      +LC_ALL=$LOCALE_FR \
>      +./test-c-snprintf${EXEEXT} 1
>      -- 
>      1.7.10.4



reply via email to

[Prev in Thread] Current Thread [Next in Thread]