Here is a revised version. It passes the included tests, so I'll wait 72 hours for comments and then commit it if no one objects.
--8<--------------------------cut here-------------------------->8-- From: Ben Pfaff <b...@cs.stanford.edu> Date: Sat, 15 Dec 2012 22:11:03 -0800 Subject: [PATCH] New 'c-*printf' modules for formatted output in C locale. New module 'c-vasnprintf'. * modules/c-vasnprintf: New file. * lib/c-vasnprintf.c: New file. * lib/c-vasnprintf.h: New file. New module 'c-snprintf'. * modules/c-snprintf: New file. * modules/c-snprintf-tests: New file. * lib/c-snprintf.c: New file. * lib/c-snprintf.h: New file. * tests/test-c-snprintf.c: New file. * tests/test-c-snprintf.sh: New file. New module 'c-vsnprintf'. * modules/c-vsnprintf: New file. * modules/c-vsnprintf-tests: New file. * lib/c-vsnprintf.c: New file. * lib/c-vsnprintf.h: New file. * tests/test-c-vsnprintf.c: New file. * tests/test-c-vsnprintf.sh: New file. New module 'c-vasprintf'. * modules/c-vasprintf: New file. * modules/c-vasprintf-tests: New file. * lib/c-asprintf.c: New file. * lib/c-vasprintf.c: New file. * lib/c-vasprintf.h: New file. * tests/test-c-vasprintf.c +: New file. * tests/test-c-vasprintf.sh: New file. New module 'c-xvasprintf'. * modules/c-xvasprintf: New file. * modules/c-xvasprintf-tests: New file. * lib/c-xasprintf.c: New file. * lib/c-xvasprintf.c: New file. * lib/c-xvasprintf.h: New file. * tests/test-c-xvasprintf.c: New file. * tests/test-c-xvasprintf.sh: New file. --- ChangeLog | 43 ++++++++++++++++++++++++ lib/c-asprintf.c | 35 +++++++++++++++++++ lib/c-snprintf.c | 75 +++++++++++++++++++++++++++++++++++++++++ lib/c-snprintf.h | 46 +++++++++++++++++++++++++ lib/c-vasnprintf.c | 43 ++++++++++++++++++++++++ lib/c-vasnprintf.h | 76 +++++++++++++++++++++++++++++++++++++++++ lib/c-vasprintf.c | 46 +++++++++++++++++++++++++ lib/c-vasprintf.h | 51 ++++++++++++++++++++++++++++ lib/c-vsnprintf.c | 74 ++++++++++++++++++++++++++++++++++++++++ lib/c-vsnprintf.h | 49 +++++++++++++++++++++++++++ lib/c-xasprintf.c | 34 +++++++++++++++++++ lib/c-xvasprintf.c | 40 ++++++++++++++++++++++ lib/c-xvasprintf.h | 58 ++++++++++++++++++++++++++++++++ modules/c-snprintf | 23 +++++++++++++ modules/c-snprintf-tests | 17 ++++++++++ modules/c-vasnprintf | 55 ++++++++++++++++++++++++++++++ modules/c-vasprintf | 24 +++++++++++++ modules/c-vasprintf-tests | 17 ++++++++++ modules/c-vsnprintf | 24 +++++++++++++ modules/c-vsnprintf-tests | 17 ++++++++++ modules/c-xvasprintf | 24 +++++++++++++ modules/c-xvasprintf-tests | 18 ++++++++++ tests/test-c-snprintf.c | 58 ++++++++++++++++++++++++++++++++ tests/test-c-snprintf.sh | 15 +++++++++ tests/test-c-vasprintf.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ tests/test-c-vasprintf.sh | 15 +++++++++ tests/test-c-vsnprintf.c | 73 ++++++++++++++++++++++++++++++++++++++++ tests/test-c-vsnprintf.sh | 15 +++++++++ tests/test-c-xvasprintf.c | 78 ++++++++++++++++++++++++++++++++++++++++++ tests/test-c-xvasprintf.sh | 15 +++++++++ 30 files changed, 1238 insertions(+) create mode 100644 lib/c-asprintf.c 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 lib/c-vasprintf.c create mode 100644 lib/c-vasprintf.h create mode 100644 lib/c-vsnprintf.c create mode 100644 lib/c-vsnprintf.h create mode 100644 lib/c-xasprintf.c create mode 100644 lib/c-xvasprintf.c create mode 100644 lib/c-xvasprintf.h create mode 100644 modules/c-snprintf create mode 100644 modules/c-snprintf-tests create mode 100644 modules/c-vasnprintf create mode 100644 modules/c-vasprintf create mode 100644 modules/c-vasprintf-tests create mode 100644 modules/c-vsnprintf create mode 100644 modules/c-vsnprintf-tests create mode 100644 modules/c-xvasprintf create mode 100644 modules/c-xvasprintf-tests create mode 100644 tests/test-c-snprintf.c create mode 100755 tests/test-c-snprintf.sh create mode 100644 tests/test-c-vasprintf.c create mode 100755 tests/test-c-vasprintf.sh create mode 100644 tests/test-c-vsnprintf.c create mode 100755 tests/test-c-vsnprintf.sh create mode 100644 tests/test-c-xvasprintf.c create mode 100755 tests/test-c-xvasprintf.sh diff --git a/ChangeLog b/ChangeLog index 3e04979..9ebac20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2012-12-15 Ben Pfaff <b...@cs.stanford.edu> + + New 'c-*printf' modules for formatted output in C locale. + + New module 'c-vasnprintf'. + * modules/c-vasnprintf: New file. + * lib/c-vasnprintf.c: New file. + * lib/c-vasnprintf.h: New file. + + New module 'c-snprintf'. + * modules/c-snprintf: New file. + * modules/c-snprintf-tests: New file. + * lib/c-snprintf.c: New file. + * lib/c-snprintf.h: New file. + * tests/test-c-snprintf.c: New file. + * tests/test-c-snprintf.sh: New file. + + New module 'c-vsnprintf'. + * modules/c-vsnprintf: New file. + * modules/c-vsnprintf-tests: New file. + * lib/c-vsnprintf.c: New file. + * lib/c-vsnprintf.h: New file. + * tests/test-c-vsnprintf.c: New file. + * tests/test-c-vsnprintf.sh: New file. + + New module 'c-vasprintf'. + * modules/c-vasprintf: New file. + * modules/c-vasprintf-tests: New file. + * lib/c-asprintf.c: New file. + * lib/c-vasprintf.c: New file. + * lib/c-vasprintf.h: New file. + * tests/test-c-vasprintf.c +: New file. + * tests/test-c-vasprintf.sh: New file. + + New module 'c-xvasprintf'. + * modules/c-xvasprintf: New file. + * modules/c-xvasprintf-tests: New file. + * lib/c-xasprintf.c: New file. + * lib/c-xvasprintf.c: New file. + * lib/c-xvasprintf.h: New file. + * tests/test-c-xvasprintf.c: New file. + * tests/test-c-xvasprintf.sh: New file. + 2012-11-29 Paul Eggert <egg...@cs.ucla.edu> sys_stat: no 'static inline' diff --git a/lib/c-asprintf.c b/lib/c-asprintf.c new file mode 100644 index 0000000..f84d86f --- /dev/null +++ b/lib/c-asprintf.c @@ -0,0 +1,35 @@ +/* Formatted output to strings in C locale. + Copyright (C) 1999, 2002, 2006-2007, 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 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, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "c-vasprintf.h" + +#include <stdarg.h> + +int +c_asprintf (char **resultp, const char *format, ...) +{ + va_list args; + int result; + + va_start (args, format); + result = c_vasprintf (resultp, format, args); + va_end (args); + return result; +} diff --git a/lib/c-snprintf.c b/lib/c-snprintf.c new file mode 100644 index 0000000..18284c1 --- /dev/null +++ b/lib/c-snprintf.c @@ -0,0 +1,75 @@ +/* Formatted output to strings in C locale. + Copyright (C) 2004, 2006-2012 Free Software Foundation, Inc. + Written by Simon Josefsson and Paul Eggert. + Modified for C locale by 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..5bf75fe --- /dev/null +++ b/lib/c-snprintf.h @@ -0,0 +1,46 @@ +/* snprintf in C locale. + Copyright (C) 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/lib/c-vasprintf.c b/lib/c-vasprintf.c new file mode 100644 index 0000000..1e6f6e9 --- /dev/null +++ b/lib/c-vasprintf.c @@ -0,0 +1,46 @@ +/* Formatted output to strings in C locale. + Copyright (C) 1999, 2002, 2006-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 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, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "c-vasprintf.h" + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "c-vasnprintf.h" + +int +c_vasprintf (char **resultp, const char *format, va_list args) +{ + size_t length; + char *result = c_vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + if (length > INT_MAX) + { + free (result); + errno = EOVERFLOW; + return -1; + } + + *resultp = result; + /* Return the number of resulting bytes, excluding the trailing NUL. */ + return length; +} diff --git a/lib/c-vasprintf.h b/lib/c-vasprintf.h new file mode 100644 index 0000000..347679e --- /dev/null +++ b/lib/c-vasprintf.h @@ -0,0 +1,51 @@ +/* vasprintf and asprintf, in C locale. + Copyright (C) 2002-2004, 2006-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/>. */ + +#ifndef _C_VASPRINTF_H +#define _C_VASPRINTF_H + +/* Get va_list. */ +#include <stdarg.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 + +/* asprintf() and vasprintf(), but formatting takes place in the C locale, that + is, the decimal point used in floating-point formatting directives is always + '.'. */ +int c_asprintf (char **resultp, const char *format, ...); + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3)); +int c_vasprintf (char **resultp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _C_VASPRINTF_H */ diff --git a/lib/c-vsnprintf.c b/lib/c-vsnprintf.c new file mode 100644 index 0000000..45f8bd5 --- /dev/null +++ b/lib/c-vsnprintf.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 and Yoann Vandoorselaere <yo...@prelude-ids.org>. + Modified for C locale by 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 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, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* 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 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. + + Formatting takes place in the C locale, that is, the decimal point + used in floating-point formatting directives is always '.'. */ +int +c_vsnprintf (char *str, size_t size, const char *format, va_list args) +{ + char *output; + size_t len; + size_t lenbuf = size; + + output = c_vasnprintf (str, &lenbuf, format, args); + len = lenbuf; + + 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 (len > INT_MAX) + { + errno = EOVERFLOW; + return -1; + } + + return len; +} diff --git a/lib/c-vsnprintf.h b/lib/c-vsnprintf.h new file mode 100644 index 0000000..de881b8 --- /dev/null +++ b/lib/c-vsnprintf.h @@ -0,0 +1,49 @@ +/* vsnprintf in C locale. + Copyright (C) 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_VSNPRINTF_H +#define _C_VSNPRINTF_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get va_list. */ +#include <stdarg.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_vsnprintf (char *str, size_t size, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _C_VSNPRINTF_H */ diff --git a/lib/c-xasprintf.c b/lib/c-xasprintf.c new file mode 100644 index 0000000..9c1059b --- /dev/null +++ b/lib/c-xasprintf.c @@ -0,0 +1,34 @@ +/* vasprintf and asprintf with out-of-memory checking in C locale. + Copyright (C) 1999, 2002-2004, 2006, 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> + +/* Specification. */ +#include "c-xvasprintf.h" + +char * +c_xasprintf (const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = c_xvasprintf (format, args); + va_end (args); + + return result; +} diff --git a/lib/c-xvasprintf.c b/lib/c-xvasprintf.c new file mode 100644 index 0000000..87be542 --- /dev/null +++ b/lib/c-xvasprintf.c @@ -0,0 +1,40 @@ +/* vasprintf with out-of-memory checking in C locale. + Copyright (C) 1999, 2002-2004, 2006-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> + +/* Specification. */ +#include "c-xvasprintf.h" + +#include <errno.h> +#include <stdio.h> + +#include "xalloc.h" + +char * +c_xvasprintf (const char *format, va_list args) +{ + char *result; + + if (c_vasprintf (&result, format, args) < 0) + { + if (errno == ENOMEM) + xalloc_die (); + return NULL; + } + + return result; +} diff --git a/lib/c-xvasprintf.h b/lib/c-xvasprintf.h new file mode 100644 index 0000000..5c82034 --- /dev/null +++ b/lib/c-xvasprintf.h @@ -0,0 +1,58 @@ +/* vasprintf and asprintf, with out-of-memory checking, in C locale. + Copyright (C) 2002-2004, 2006-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/>. */ + +#ifndef _C_XVASPRINTF_H +#define _C_XVASPRINTF_H + +/* Get va_list. */ +#include <stdarg.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(), + and return it. Upon [ENOMEM] memory allocation error, call xalloc_die. + On some other error + - [EOVERFLOW] resulting string length is > INT_MAX, + - [EINVAL] invalid format string, + - [EILSEQ] error during conversion between wide and multibyte characters, + return NULL. + + Formatting takes place in the C locale, that is, the decimal point + used in floating-point formatting directives is always '.'. */ +extern char *c_xasprintf (const char *format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2)); +extern char *c_xvasprintf (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _C_XVASPRINTF_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/modules/c-vasprintf b/modules/c-vasprintf new file mode 100644 index 0000000..78e4119 --- /dev/null +++ b/modules/c-vasprintf @@ -0,0 +1,24 @@ +Description: +asprintf() and vasprintf() in C locale + +Files: +lib/c-vasprintf.h +lib/c-asprintf.c +lib/c-vasprintf.c + +Depends-on: +c-vasnprintf + +configure.ac: + +Makefile.am: +lib_SOURCES += c-asprintf.c c-vasprintf.c + +Include: +"c-vasprintf.h" + +License: +GPL + +Maintainer: +Ben Pfaff diff --git a/modules/c-vasprintf-tests b/modules/c-vasprintf-tests new file mode 100644 index 0000000..9409563 --- /dev/null +++ b/modules/c-vasprintf-tests @@ -0,0 +1,17 @@ +Files: +tests/test-c-vasprintf.c +tests/test-c-vasprintf.sh +m4/locale-fr.m4 +tests/macros.h + +Depends-on: +setlocale +snprintf + +configure.ac: +gt_LOCALE_FR + +Makefile.am: +TESTS += test-c-vasprintf.sh +check_PROGRAMS += test-c-vasprintf +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' diff --git a/modules/c-vsnprintf b/modules/c-vsnprintf new file mode 100644 index 0000000..7846d9d --- /dev/null +++ b/modules/c-vsnprintf @@ -0,0 +1,24 @@ +Description: +c_vsnprintf(): print formatted output from an stdarg argument listto a +fixed length string in C locale + +Files: +lib/c-vsnprintf.h +lib/c-vsnprintf.c + +Depends-on: +c-vasnprintf + +configure.ac: + +Makefile.am: +lib_SOURCES += c-vsnprintf.c + +Include: +"c-vsnprintf.h" + +License: +GPL + +Maintainer: +Ben Pfaff diff --git a/modules/c-vsnprintf-tests b/modules/c-vsnprintf-tests new file mode 100644 index 0000000..6a76092 --- /dev/null +++ b/modules/c-vsnprintf-tests @@ -0,0 +1,17 @@ +Files: +tests/test-c-vsnprintf.c +tests/test-c-vsnprintf.sh +m4/locale-fr.m4 +tests/macros.h + +Depends-on: +setlocale +snprintf + +configure.ac: +gt_LOCALE_FR + +Makefile.am: +TESTS += test-c-vsnprintf.sh +check_PROGRAMS += test-c-vsnprintf +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' diff --git a/modules/c-xvasprintf b/modules/c-xvasprintf new file mode 100644 index 0000000..e6681e8 --- /dev/null +++ b/modules/c-xvasprintf @@ -0,0 +1,24 @@ +Description: +c_asprintf and c_vasprintf with out-of-memory checking. Also see xalloc-die. + +Files: +lib/c-xvasprintf.h +lib/c-xasprintf.c +lib/c-xvasprintf.c + +Depends-on: +c-vasprintf + +configure.ac: + +Makefile.am: +lib_SOURCES += c-xasprintf.c c-xvasprintf.c + +Include: +"c-xvasprintf.h" + +License: +GPL + +Maintainer: +Ben Pfaff diff --git a/modules/c-xvasprintf-tests b/modules/c-xvasprintf-tests new file mode 100644 index 0000000..b5a9262 --- /dev/null +++ b/modules/c-xvasprintf-tests @@ -0,0 +1,18 @@ +Files: +tests/test-c-xvasprintf.c +tests/test-c-xvasprintf.sh +m4/locale-fr.m4 +tests/macros.h + +Depends-on: +setlocale +snprintf +xalloc + +configure.ac: +gt_LOCALE_FR + +Makefile.am: +TESTS += test-c-xvasprintf.sh +check_PROGRAMS += test-c-xvasprintf +TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' diff --git a/tests/test-c-snprintf.c b/tests/test-c-snprintf.c new file mode 100644 index 0000000..d178b3f --- /dev/null +++ b/tests/test-c-snprintf.c @@ -0,0 +1,58 @@ +/* Test of c_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 diff --git a/tests/test-c-vasprintf.c b/tests/test-c-vasprintf.c new file mode 100644 index 0000000..00e7df4 --- /dev/null +++ b/tests/test-c-vasprintf.c @@ -0,0 +1,80 @@ +/* Test of c_asprintf() and c_vasprintf() functions. + 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-vasprintf.h" + +#include <locale.h> +#include <stdio.h> +#include <string.h> + +#include "macros.h" + +static int +my_c_asprintf (char **result, const char *format, ...) +{ + va_list args; + int ret; + + va_start (args, format); + ret = c_vasprintf (result, format, args); + va_end (args); + return ret; +} + +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_asprintf() and c_vasprintf(). + They should always use '.' as the decimal point. */ + { + int retval; + char *s; + + retval = c_asprintf (&s, "%#.0f", 1.0); + ASSERT (s != NULL); + ASSERT (!strcmp (s, "1.")); + ASSERT (retval == 2); + free (s); + + retval = my_c_asprintf (&s, "%#.0f", 1.0); + ASSERT (s != NULL); + ASSERT (!strcmp (s, "1.")); + ASSERT (retval == 2); + free (s); + } + + return 0; +} diff --git a/tests/test-c-vasprintf.sh b/tests/test-c-vasprintf.sh new file mode 100755 index 0000000..525c0ef --- /dev/null +++ b/tests/test-c-vasprintf.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-vasprintf${EXEEXT} 1 diff --git a/tests/test-c-vsnprintf.c b/tests/test-c-vsnprintf.c new file mode 100644 index 0000000..d504c2e --- /dev/null +++ b/tests/test-c-vsnprintf.c @@ -0,0 +1,73 @@ +/* Test of c_vsnprintf() 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-vsnprintf.h" + +#include <locale.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include "macros.h" + +#include <string.h> + +static int +my_c_snprintf (char *buf, int size, const char *format, ...) +{ + va_list args; + int ret; + + va_start (args, format); + ret = c_vsnprintf (buf, size, format, args); + va_end (args); + return ret; +} + +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_vsnprintf(). + It should always use '.' as the decimal point. */ + { + char s[16]; + + my_c_snprintf (s, sizeof s, "%#.0f", 1.0); + ASSERT (!strcmp (s, "1.")); + } + + return 0; +} diff --git a/tests/test-c-vsnprintf.sh b/tests/test-c-vsnprintf.sh new file mode 100755 index 0000000..b173a38 --- /dev/null +++ b/tests/test-c-vsnprintf.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-vsnprintf${EXEEXT} 1 diff --git a/tests/test-c-xvasprintf.c b/tests/test-c-xvasprintf.c new file mode 100644 index 0000000..a5c5268 --- /dev/null +++ b/tests/test-c-xvasprintf.c @@ -0,0 +1,78 @@ +/* Test of c_xasprintf() and c_xvasprintf() functions. + 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-xvasprintf.h" + +#include <locale.h> +#include <stdio.h> +#include <string.h> + +#include "macros.h" + +static char * +my_c_xasprintf (const char *format, ...) +{ + va_list args; + char *s; + + va_start (args, format); + s = c_xvasprintf (format, args); + va_end (args); + + return s; +} + +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_xasprintf() and c_xvasprintf(). + They should always use '.' as the decimal point. */ + { + char *s; + + s = c_xasprintf ("%#.0f", 1.0); + ASSERT (s != NULL); + ASSERT (!strcmp (s, "1.")); + free (s); + + s = my_c_xasprintf ("%#.0f", 1.0); + ASSERT (s != NULL); + ASSERT (!strcmp (s, "1.")); + free (s); + } + + return 0; +} diff --git a/tests/test-c-xvasprintf.sh b/tests/test-c-xvasprintf.sh new file mode 100755 index 0000000..1ec5e35 --- /dev/null +++ b/tests/test-c-xvasprintf.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-xvasprintf${EXEEXT} 1 -- 1.7.10.4