From f022473fdaf724d84817c4003120b9a38fbf884b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 18 Dec 2012 21:06:17 -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 b9e213b3b..427581ac0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2012-12-15 Ben Pfaff + + 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-12-18 Paul Eggert argp: better 'inline' diff --git a/lib/c-asprintf.c b/lib/c-asprintf.c new file mode 100644 index 000000000..f84d86ffc --- /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 . */ + +#include + +/* Specification. */ +#include "c-vasprintf.h" + +#include + +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 000000000..18284c1a0 --- /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 . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#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 000000000..5bf75fe6e --- /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 . */ + +#ifndef _C_SNPRINTF_H +#define _C_SNPRINTF_H + +/* Get size_t. */ +#include + +/* 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 000000000..78d1fb563 --- /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 . */ + +#include + +#include + +#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 000000000..8fc172478 --- /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 . */ + +#ifndef _C_VASNPRINTF_H +#define _C_VASNPRINTF_H + +/* Get va_list. */ +#include + +/* Get size_t. */ +#include + +/* 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 000000000..1e6f6e9f3 --- /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 . */ + +#include + +/* Specification. */ +#include "c-vasprintf.h" + +#include +#include +#include + +#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 000000000..347679ef7 --- /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 . */ + +#ifndef _C_VASPRINTF_H +#define _C_VASPRINTF_H + +/* Get va_list. */ +#include + +/* 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 000000000..45f8bd508 --- /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 . + 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 . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#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 000000000..de881b8cb --- /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 . */ + +#ifndef _C_VSNPRINTF_H +#define _C_VSNPRINTF_H + +/* Get size_t. */ +#include + +/* Get va_list. */ +#include + +/* 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 000000000..9c1059b48 --- /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 . */ + +#include + +/* 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 000000000..87be54224 --- /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 . */ + +#include + +/* Specification. */ +#include "c-xvasprintf.h" + +#include +#include + +#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 000000000..5c8203473 --- /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 . */ + +#ifndef _C_XVASPRINTF_H +#define _C_XVASPRINTF_H + +/* Get va_list. */ +#include + +/* 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 000000000..edebe2bc0 --- /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 000000000..86d6a1420 --- /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 000000000..cd9419345 --- /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 000000000..78e411993 --- /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 000000000..940956366 --- /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 000000000..7846d9d4f --- /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 000000000..6a76092dd --- /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 000000000..e6681e8e5 --- /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 000000000..b5a926221 --- /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 000000000..d178b3f01 --- /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 . */ + +#include + +#include "c-snprintf.h" + +#include +#include +#include + +#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 000000000..83051fc5d --- /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 000000000..00e7df42b --- /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 . */ + +#include + +#include "c-vasprintf.h" + +#include +#include +#include + +#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 000000000..525c0ef53 --- /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 000000000..d504c2e2a --- /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 . */ + +#include + +#include "c-vsnprintf.h" + +#include +#include +#include +#include + +#include "macros.h" + +#include + +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 000000000..b173a382a --- /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 000000000..a5c526816 --- /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 . */ + +#include + +#include "c-xvasprintf.h" + +#include +#include +#include + +#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 000000000..1ec5e35cd --- /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 -- 2.11.0