Here come the c-*zs*printf modules, which are like the existing c-*s*printf
modules, except that
- they support returning results of length > INT_MAX,
- thus the length type is changed to 'ptrdiff_t' from 'int',
- an attempt to return a result > PTRDIFF_MAX produces an error
ENOMEM (consistently with malloc, calloc) instead of EOVERFLOW.
Module dependencies:
c-snprintf -> c-vzsnprintf
c-zsnprintf -> c-vasnprintf
c-vasprintf -> c-vasnprintf
c-vazsprintf -> c-vasnprintf
c-vsnprintf -> c-vzsnprintf
c-vzsnprintf -> c-vasnprintf
c-xvasprintf -> c-vazsprintf
Since I'm replacing the implementation of all these modules, I'm taking
the opportunity to change their licenses from GPL to LGPL or LGPLv2+.
This makes sense because
- these functions can reasonably be used in libraries,
- some of them could also be implemented based on *printf_l functions
that exist in the libc of macOS, FreeBSD, NetBSD.
I can do this because
- I'm basing the new implementation on the modules without 'c-', which
are already under LGPL / LGPLv2+, and
- the remaining code pieces contributed by Ben Pfaff are below the
10-lines threshold, cf.
<https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html>.
2024-06-22 Bruno Haible <[email protected]>
c-xvasprintf: Guarantee a non-NULL result.
* lib/c-xvasprintf.h: Clarify the programmer's responsibilities.
(c_xasprintf, c_xvasprintf): Declare as returning non-NULL.
* lib/c-xvasprintf.c: Include <stdlib.h>, <string.h>.
(c_xvasprintf): Call c_vazsprintf instead of c_vasprintf. When some
other error occurs, emit an error message and abort.
* modules/c-xvasprintf (Files): Add m4/strerrorname_np.m4.
(Depends-on): Add extensions, c-vazsprintf. Remove c-vasprintf.
(configure.ac): Invoke gl_OPTIONAL_STRERRORNAME_NP.
* NEWS: Mention the change.
2024-06-22 Bruno Haible <[email protected]>
c-vasprintf: Make return convention consistent with other modules.
* lib/c-vasprintf.h (c_asprintf, c_vasprintf): Add specification.
* lib/c-asprintf.c: Replaced with code based on lib/asprintf.c.
* lib/c-vasprintf.c: Replaced with code based on lib/vasprintf.c.
* modules/c-vasprintf (Depends-on): Add stdint.
(License): Change to LGPLv2+.
c-vazsprintf: New module.
* lib/c-vasprintf.h: Change license to LGPLv2+.
Include <stddef.h>.
(c_azsprintf, c_vazsprintf): New declarations.
* lib/c-azsprintf.c: New file, based on lib/azsprintf.c.
* lib/c-vazsprintf.c: New file, based on lib/vazsprintf.c.
* modules/c-vazsprintf: New file.
2024-06-22 Bruno Haible <[email protected]>
c-snprintf: Use c-vzsnprintf.
* lib/c-snprintf.h (c_snprintf): Move specification to here.
* lib/c-snprintf.c: Change license to LGPLv2+.
Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
<stdint.h>, c-vsnprintf.h.
(c_snprintf): Implement based on c_vzsnprintf.
* modules/c-snprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
c-vasnprintf.
c-zsnprintf: New module.
* lib/c-snprintf.h: Change license to LGPLv2+.
(c_zsnprintf): New declaration.
* lib/c-zsnprintf.c: New file, based on lib/zsnprintf.c.
* modules/c-zsnprintf: New file.
2024-06-22 Bruno Haible <[email protected]>
c-vsnprintf: Use c-vzsnprintf.
* lib/c-vsnprintf.h (c_vsnprintf): Move specification to here.
* lib/c-vsnprintf.c: Change license to LGPLv2+.
Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
<stdint.h>.
(c_vsnprintf): Implement based on c_vzsnprintf.
* modules/c-vsnprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
c-vasnprintf.
(License): Change to LGPLv2+.
c-vzsnprintf: New module.
* lib/c-vsnprintf.h: Change license to LGPLv2+.
(c_vzsnprintf): New declaration.
* lib/c-vzsnprintf.c: New file, based on lib/vzsnprintf.c.
* modules/c-vzsnprintf: New file.
>From 9c456389c96b0532596ea62bcc320f549540d10c Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:11 +0200
Subject: [PATCH 1/7] c-vzsnprintf: New module.
* lib/c-vsnprintf.h: Change license to LGPLv2+.
(c_vzsnprintf): New declaration.
* lib/c-vzsnprintf.c: New file, based on lib/vzsnprintf.c.
* modules/c-vzsnprintf: New file.
---
ChangeLog | 8 ++++++
lib/c-vsnprintf.h | 34 +++++++++++++++++------
lib/c-vzsnprintf.c | 66 ++++++++++++++++++++++++++++++++++++++++++++
modules/c-vzsnprintf | 27 ++++++++++++++++++
4 files changed, 126 insertions(+), 9 deletions(-)
create mode 100644 lib/c-vzsnprintf.c
create mode 100644 modules/c-vzsnprintf
diff --git a/ChangeLog b/ChangeLog
index ef21dcc222..0f37171285 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-06-22 Bruno Haible <[email protected]>
+
+ c-vzsnprintf: New module.
+ * lib/c-vsnprintf.h: Change license to LGPLv2+.
+ (c_vzsnprintf): New declaration.
+ * lib/c-vzsnprintf.c: New file, based on lib/vzsnprintf.c.
+ * modules/c-vzsnprintf: New file.
+
2024-06-22 Bruno Haible <[email protected]>
xvasprintf: Guarantee a non-NULL result.
diff --git a/lib/c-vsnprintf.h b/lib/c-vsnprintf.h
index 57d689e297..e00ade93f8 100644
--- a/lib/c-vsnprintf.h
+++ b/lib/c-vsnprintf.h
@@ -1,18 +1,18 @@
/* vsnprintf in C locale.
Copyright (C) 2012-2024 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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 <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _C_VSNPRINTF_H
#define _C_VSNPRINTF_H
@@ -22,7 +22,7 @@
#error "Please include config.h first."
#endif
-/* Get size_t. */
+/* Get size_t, ptrdiff_t. */
#include <stddef.h>
/* Get va_list. */
@@ -35,6 +35,22 @@
extern "C" {
#endif
+/* Prints formatted output to string STR. Similar to vsprintf, but the
+ additional parameter SIZE limits how much is written into STR.
+ STR may be NULL, in which case nothing will be written.
+ Returns the string length of the formatted string (which may be larger
+ than SIZE). Upon failure, returns -1 with errno set.
+
+ Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+ Therefore, if the format string is valid and does not use %ls/%lc
+ directives nor widths, the only possible failure code is ENOMEM.
+
+ Formatting takes place in the C locale, that is, the decimal point
+ used in floating-point formatting directives is always '.'. */
+extern ptrdiff_t c_vzsnprintf (char *restrict str, size_t size,
+ const char *format, va_list args)
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
+
extern int c_vsnprintf (char *restrict str, size_t size,
const char *format, va_list args)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
diff --git a/lib/c-vzsnprintf.c b/lib/c-vzsnprintf.c
new file mode 100644
index 0000000000..948266dd99
--- /dev/null
+++ b/lib/c-vzsnprintf.c
@@ -0,0 +1,66 @@
+/* Formatted output to strings in C locale.
+ Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc.
+ Written by Simon Josefsson and Yoann Vandoorselaere <[email protected]>.
+ Modified for C locale by Ben Pfaff.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "c-vsnprintf.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "c-vasnprintf.h"
+
+ptrdiff_t
+c_vzsnprintf (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 > PTRDIFF_MAX)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return len;
+}
diff --git a/modules/c-vzsnprintf b/modules/c-vzsnprintf
new file mode 100644
index 0000000000..4049974f4a
--- /dev/null
+++ b/modules/c-vzsnprintf
@@ -0,0 +1,27 @@
+Description:
+c_vzsnprintf(): print formatted output from an stdarg argument list to a
+fixed length string (without INT_MAX limitation) in C locale
+
+Files:
+lib/c-vsnprintf.h
+lib/c-vzsnprintf.c
+
+Depends-on:
+stdint
+stdio
+c-vasnprintf
+
+configure.ac:
+AC_REQUIRE([AC_C_RESTRICT])
+
+Makefile.am:
+lib_SOURCES += c-vzsnprintf.c
+
+Include:
+"c-vsnprintf.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
--
2.34.1
>From 77838df62e9f3a1a6b5bcdf35cac1bfb55487764 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:20 +0200
Subject: [PATCH 2/7] c-vsnprintf: Use c-vzsnprintf.
* lib/c-vsnprintf.h (c_vsnprintf): Move specification to here.
* lib/c-vsnprintf.c: Change license to LGPLv2+.
Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
<stdint.h>.
(c_vsnprintf): Implement based on c_vzsnprintf.
* modules/c-vsnprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
c-vasnprintf.
(License): Change to LGPLv2+.
---
ChangeLog | 10 +++++++++
lib/c-vsnprintf.c | 53 ++++++++++-----------------------------------
lib/c-vsnprintf.h | 8 +++++++
modules/c-vsnprintf | 7 +++---
4 files changed, 33 insertions(+), 45 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 0f37171285..9326d490e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2024-06-22 Bruno Haible <[email protected]>
+ c-vsnprintf: Use c-vzsnprintf.
+ * lib/c-vsnprintf.h (c_vsnprintf): Move specification to here.
+ * lib/c-vsnprintf.c: Change license to LGPLv2+.
+ Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
+ <stdint.h>.
+ (c_vsnprintf): Implement based on c_vzsnprintf.
+ * modules/c-vsnprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
+ c-vasnprintf.
+ (License): Change to LGPLv2+.
+
c-vzsnprintf: New module.
* lib/c-vsnprintf.h: Change license to LGPLv2+.
(c_vzsnprintf): New declaration.
diff --git a/lib/c-vsnprintf.c b/lib/c-vsnprintf.c
index fca53fff88..941c2d4609 100644
--- a/lib/c-vsnprintf.c
+++ b/lib/c-vsnprintf.c
@@ -1,19 +1,17 @@
/* Formatted output to strings in C locale.
Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc.
- Written by Simon Josefsson and Yoann Vandoorselaere <[email protected]>.
- Modified for C locale by Ben Pfaff.
This file 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.
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
@@ -26,49 +24,20 @@
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <stdint.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;
+ ptrdiff_t ret = c_vzsnprintf (str, size, format, 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 (len > INT_MAX)
+#if PTRDIFF_MAX > INT_MAX
+ if (ret > INT_MAX)
{
errno = EOVERFLOW;
return -1;
}
+#endif
- return len;
+ return ret;
}
diff --git a/lib/c-vsnprintf.h b/lib/c-vsnprintf.h
index e00ade93f8..ff9cc2250c 100644
--- a/lib/c-vsnprintf.h
+++ b/lib/c-vsnprintf.h
@@ -51,6 +51,14 @@ extern ptrdiff_t c_vzsnprintf (char *restrict str, size_t size,
const char *format, va_list args)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
+/* Prints formatted output to string STR. Similar to sprintf, but the
+ additional parameter SIZE limits how much is written into STR.
+ STR may be NULL, in which case nothing will be written.
+ Returns the string length of the formatted string (which may be larger
+ than SIZE). Upon failure, returns -1 with errno set.
+
+ Formatting takes place in the C locale, that is, the decimal point
+ used in floating-point formatting directives is always '.'. */
extern int c_vsnprintf (char *restrict str, size_t size,
const char *format, va_list args)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
diff --git a/modules/c-vsnprintf b/modules/c-vsnprintf
index 8188a96d39..835968f96a 100644
--- a/modules/c-vsnprintf
+++ b/modules/c-vsnprintf
@@ -7,8 +7,9 @@ lib/c-vsnprintf.h
lib/c-vsnprintf.c
Depends-on:
+stdint
stdio
-c-vasnprintf
+c-vzsnprintf
configure.ac:
AC_REQUIRE([AC_C_RESTRICT])
@@ -20,7 +21,7 @@ Include:
"c-vsnprintf.h"
License:
-GPL
+LGPLv2+
Maintainer:
-Ben Pfaff
+all
--
2.34.1
>From 7afd9e0f392c2a5982e157958a528bb9ddcf96bc Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:29 +0200
Subject: [PATCH 3/7] c-zsnprintf: New module.
* lib/c-snprintf.h: Change license to LGPLv2+.
(c_zsnprintf): New declaration.
* lib/c-zsnprintf.c: New file, based on lib/zsnprintf.c.
* modules/c-zsnprintf: New file.
---
ChangeLog | 8 ++++++
lib/c-snprintf.h | 34 ++++++++++++++++-------
lib/c-zsnprintf.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
modules/c-zsnprintf | 27 +++++++++++++++++++
4 files changed, 126 insertions(+), 9 deletions(-)
create mode 100644 lib/c-zsnprintf.c
create mode 100644 modules/c-zsnprintf
diff --git a/ChangeLog b/ChangeLog
index 9326d490e7..83445e3e8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-06-22 Bruno Haible <[email protected]>
+
+ c-zsnprintf: New module.
+ * lib/c-snprintf.h: Change license to LGPLv2+.
+ (c_zsnprintf): New declaration.
+ * lib/c-zsnprintf.c: New file, based on lib/zsnprintf.c.
+ * modules/c-zsnprintf: New file.
+
2024-06-22 Bruno Haible <[email protected]>
c-vsnprintf: Use c-vzsnprintf.
diff --git a/lib/c-snprintf.h b/lib/c-snprintf.h
index 8e2ab729d7..8e4a6cbe59 100644
--- a/lib/c-snprintf.h
+++ b/lib/c-snprintf.h
@@ -1,18 +1,18 @@
/* snprintf in C locale.
Copyright (C) 2012-2024 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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 <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _C_SNPRINTF_H
#define _C_SNPRINTF_H
@@ -22,7 +22,7 @@
#error "Please include config.h first."
#endif
-/* Get size_t. */
+/* Get size_t, ptrdiff_t. */
#include <stddef.h>
/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD. */
@@ -32,6 +32,22 @@
extern "C" {
#endif
+/* Prints formatted output to string STR. Similar to sprintf, but the
+ additional parameter SIZE limits how much is written into STR.
+ STR may be NULL, in which case nothing will be written.
+ Returns the string length of the formatted string (which may be larger
+ than SIZE). Upon failure, returns -1 with errno set.
+
+ Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+ Therefore, if the format string is valid and does not use %ls/%lc
+ directives nor widths, the only possible failure code is ENOMEM.
+
+ Formatting takes place in the C locale, that is, the decimal point
+ used in floating-point formatting directives is always '.'. */
+extern ptrdiff_t c_zsnprintf (char *restrict str, size_t size,
+ const char *format, ...)
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 4));
+
extern int c_snprintf (char *restrict str, size_t size,
const char *format, ...)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 4));
diff --git a/lib/c-zsnprintf.c b/lib/c-zsnprintf.c
new file mode 100644
index 0000000000..85ed3f9191
--- /dev/null
+++ b/lib/c-zsnprintf.c
@@ -0,0 +1,66 @@
+/* Formatted output to strings in C locale.
+ Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc.
+ Written by Simon Josefsson and Paul Eggert.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-snprintf.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "c-vasnprintf.h"
+
+ptrdiff_t
+c_zsnprintf (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 (len > PTRDIFF_MAX)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return len;
+}
diff --git a/modules/c-zsnprintf b/modules/c-zsnprintf
new file mode 100644
index 0000000000..5410db03cd
--- /dev/null
+++ b/modules/c-zsnprintf
@@ -0,0 +1,27 @@
+Description:
+c_zsnprintf(): print formatted output to a fixed length string (without
+INT_MAX limitation) in C locale
+
+Files:
+lib/c-snprintf.h
+lib/c-zsnprintf.c
+
+Depends-on:
+stdint
+stdio
+c-vasnprintf
+
+configure.ac:
+AC_REQUIRE([AC_C_RESTRICT])
+
+Makefile.am:
+lib_SOURCES += c-zsnprintf.c
+
+Include:
+"c-snprintf.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
--
2.34.1
>From eaf2341422e0b74d594839556f74d19dcce839c1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:35 +0200
Subject: [PATCH 4/7] c-snprintf: Use c-vzsnprintf.
* lib/c-snprintf.h (c_snprintf): Move specification to here.
* lib/c-snprintf.c: Change license to LGPLv2+.
Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
<stdint.h>, c-vsnprintf.h.
(c_snprintf): Implement based on c_vzsnprintf.
* modules/c-snprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
c-vasnprintf.
---
ChangeLog | 9 +++++++
lib/c-snprintf.c | 59 +++++++++++++---------------------------------
lib/c-snprintf.h | 8 +++++++
modules/c-snprintf | 7 +++---
4 files changed, 37 insertions(+), 46 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 83445e3e8c..fcc60208f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2024-06-22 Bruno Haible <[email protected]>
+ c-snprintf: Use c-vzsnprintf.
+ * lib/c-snprintf.h (c_snprintf): Move specification to here.
+ * lib/c-snprintf.c: Change license to LGPLv2+.
+ Don't include <stdlib.h>, <string.h>, c-vasnprintf.h. Include
+ <stdint.h>, c-vsnprintf.h.
+ (c_snprintf): Implement based on c_vzsnprintf.
+ * modules/c-snprintf (Depends-on): Add stdint, c-vzsnprintf. Remove
+ c-vasnprintf.
+
c-zsnprintf: New module.
* lib/c-snprintf.h: Change license to LGPLv2+.
(c_zsnprintf): New declaration.
diff --git a/lib/c-snprintf.c b/lib/c-snprintf.c
index 8ded5a8fd2..658f3faed4 100644
--- a/lib/c-snprintf.c
+++ b/lib/c-snprintf.c
@@ -1,20 +1,18 @@
/* Formatted output to strings in C locale.
Copyright (C) 2004, 2006-2024 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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 <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -24,52 +22,27 @@
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <stdint.h>
-#include "c-vasnprintf.h"
+#include "c-vsnprintf.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;
+ ptrdiff_t ret;
va_start (args, format);
- output = c_vasnprintf (str, &lenbuf, format, args);
- len = lenbuf;
+ ret = c_vzsnprintf (str, size, format, args);
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)
+#if PTRDIFF_MAX > INT_MAX
+ if (ret > INT_MAX)
{
errno = EOVERFLOW;
return -1;
}
+#endif
- return len;
+ return ret;
}
diff --git a/lib/c-snprintf.h b/lib/c-snprintf.h
index 8e4a6cbe59..f52e058e9e 100644
--- a/lib/c-snprintf.h
+++ b/lib/c-snprintf.h
@@ -48,6 +48,14 @@ extern ptrdiff_t c_zsnprintf (char *restrict str, size_t size,
const char *format, ...)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 4));
+/* Prints formatted output to string STR. Similar to sprintf, but the
+ additional parameter SIZE limits how much is written into STR.
+ STR may be NULL, in which case nothing will be written.
+ Returns the string length of the formatted string (which may be larger
+ than SIZE). Upon failure, returns -1 with errno set.
+
+ Formatting takes place in the C locale, that is, the decimal point
+ used in floating-point formatting directives is always '.'. */
extern int c_snprintf (char *restrict str, size_t size,
const char *format, ...)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 4));
diff --git a/modules/c-snprintf b/modules/c-snprintf
index 456691d868..49857beca7 100644
--- a/modules/c-snprintf
+++ b/modules/c-snprintf
@@ -6,8 +6,9 @@ lib/c-snprintf.h
lib/c-snprintf.c
Depends-on:
+stdint
stdio
-c-vasnprintf
+c-vzsnprintf
configure.ac:
AC_REQUIRE([AC_C_RESTRICT])
@@ -19,7 +20,7 @@ Include:
"c-snprintf.h"
License:
-GPL
+LGPLv2+
Maintainer:
-Ben Pfaff
+all
--
2.34.1
>From 70d42c559229eb99ae41914ccca4f02c75d5a0bf Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:46 +0200
Subject: [PATCH 5/7] c-vazsprintf: New module.
* lib/c-vasprintf.h: Change license to LGPLv2+.
Include <stddef.h>.
(c_azsprintf, c_vazsprintf): New declarations.
* lib/c-azsprintf.c: New file, based on lib/azsprintf.c.
* lib/c-vazsprintf.c: New file, based on lib/vazsprintf.c.
* modules/c-vazsprintf: New file.
---
ChangeLog | 10 ++++++++++
lib/c-azsprintf.c | 34 ++++++++++++++++++++++++++++++++
lib/c-vasprintf.h | 34 +++++++++++++++++++++++++-------
lib/c-vazsprintf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
modules/c-vazsprintf | 26 +++++++++++++++++++++++++
5 files changed, 143 insertions(+), 7 deletions(-)
create mode 100644 lib/c-azsprintf.c
create mode 100644 lib/c-vazsprintf.c
create mode 100644 modules/c-vazsprintf
diff --git a/ChangeLog b/ChangeLog
index fcc60208f5..7a2dd7375c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-06-22 Bruno Haible <[email protected]>
+
+ c-vazsprintf: New module.
+ * lib/c-vasprintf.h: Change license to LGPLv2+.
+ Include <stddef.h>.
+ (c_azsprintf, c_vazsprintf): New declarations.
+ * lib/c-azsprintf.c: New file, based on lib/azsprintf.c.
+ * lib/c-vazsprintf.c: New file, based on lib/vazsprintf.c.
+ * modules/c-vazsprintf: New file.
+
2024-06-22 Bruno Haible <[email protected]>
c-snprintf: Use c-vzsnprintf.
diff --git a/lib/c-azsprintf.c b/lib/c-azsprintf.c
new file mode 100644
index 0000000000..78bc973ef5
--- /dev/null
+++ b/lib/c-azsprintf.c
@@ -0,0 +1,34 @@
+/* Formatted output to strings in C locale.
+ Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-vasprintf.h"
+
+#include <stdarg.h>
+
+ptrdiff_t
+c_azsprintf (char **resultp, const char *format, ...)
+{
+ va_list args;
+ ptrdiff_t result;
+
+ va_start (args, format);
+ result = c_vazsprintf (resultp, format, args);
+ va_end (args);
+ return result;
+}
diff --git a/lib/c-vasprintf.h b/lib/c-vasprintf.h
index ca8fa63e35..7eae757e3a 100644
--- a/lib/c-vasprintf.h
+++ b/lib/c-vasprintf.h
@@ -1,17 +1,17 @@
/* vasprintf and asprintf, in C locale.
Copyright (C) 2002-2004, 2006-2024 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _C_VASPRINTF_H
@@ -25,6 +25,9 @@
/* Get va_list. */
#include <stdarg.h>
+/* Get ptrdiff_t. */
+#include <stddef.h>
+
/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD. */
#include <stdio.h>
@@ -32,6 +35,23 @@
extern "C" {
#endif
+/* Prints formatted output to a string dynamically allocated with malloc().
+ If the memory allocation succeeds, it stores the address of the string in
+ *RESULT and returns the number of resulting bytes, excluding the trailing
+ NUL. Upon memory allocation error, or some other error, it returns -1
+ with errno set.
+
+ Failure code EOVERFLOW can only occur when a width > INT_MAX is used.
+ Therefore, if the format string is valid and does not use %ls/%lc
+ directives nor widths, the only possible failure code is ENOMEM.
+
+ Formatting takes place in the C locale, that is, the decimal point
+ used in floating-point formatting directives is always '.'. */
+ptrdiff_t c_azsprintf (char **resultp, const char *format, ...)
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 2, 3));
+ptrdiff_t c_vazsprintf (char **resultp, const char *format, va_list args)
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 2, 0));
+
/* asprintf() and vasprintf(), but formatting takes place in the C locale, that
is, the decimal point used in floating-point formatting directives is always
'.'. */
diff --git a/lib/c-vazsprintf.c b/lib/c-vazsprintf.c
new file mode 100644
index 0000000000..88ab938489
--- /dev/null
+++ b/lib/c-vazsprintf.c
@@ -0,0 +1,46 @@
+/* Formatted output to strings in C locale.
+ Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-vasprintf.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "c-vasnprintf.h"
+
+ptrdiff_t
+c_vazsprintf (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 > PTRDIFF_MAX)
+ {
+ free (result);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ *resultp = result;
+ /* Return the number of resulting bytes, excluding the trailing NUL. */
+ return length;
+}
diff --git a/modules/c-vazsprintf b/modules/c-vazsprintf
new file mode 100644
index 0000000000..5cea385926
--- /dev/null
+++ b/modules/c-vazsprintf
@@ -0,0 +1,26 @@
+Description:
+azsprintf() and vazsprintf() in C locale
+
+Files:
+lib/c-vasprintf.h
+lib/c-azsprintf.c
+lib/c-vazsprintf.c
+
+Depends-on:
+stdint
+stdio
+c-vasnprintf
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += c-azsprintf.c c-vazsprintf.c
+
+Include:
+"c-vasprintf.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
--
2.34.1
>From 82c0381e34d872590dfd3260c94e79d01da104a3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:21:51 +0200
Subject: [PATCH 6/7] c-vasprintf: Make return convention consistent with other
modules.
* lib/c-vasprintf.h (c_asprintf, c_vasprintf): Add specification.
* lib/c-asprintf.c: Replaced with code based on lib/asprintf.c.
* lib/c-vasprintf.c: Replaced with code based on lib/vasprintf.c.
* modules/c-vasprintf (Depends-on): Add stdint.
(License): Change to LGPLv2+.
---
ChangeLog | 7 +++++++
lib/c-asprintf.c | 10 +++++-----
lib/c-vasprintf.c | 22 ++++++++++++++++------
lib/c-vasprintf.h | 10 +++++++---
modules/c-vasprintf | 3 ++-
5 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7a2dd7375c..f3aec5b928 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2024-06-22 Bruno Haible <[email protected]>
+ c-vasprintf: Make return convention consistent with other modules.
+ * lib/c-vasprintf.h (c_asprintf, c_vasprintf): Add specification.
+ * lib/c-asprintf.c: Replaced with code based on lib/asprintf.c.
+ * lib/c-vasprintf.c: Replaced with code based on lib/vasprintf.c.
+ * modules/c-vasprintf (Depends-on): Add stdint.
+ (License): Change to LGPLv2+.
+
c-vazsprintf: New module.
* lib/c-vasprintf.h: Change license to LGPLv2+.
Include <stddef.h>.
diff --git a/lib/c-asprintf.c b/lib/c-asprintf.c
index c6f7719531..f626c5207b 100644
--- a/lib/c-asprintf.c
+++ b/lib/c-asprintf.c
@@ -3,16 +3,16 @@
Inc.
This file 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.
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
diff --git a/lib/c-vasprintf.c b/lib/c-vasprintf.c
index 5adaec93f2..81d45ce0ac 100644
--- a/lib/c-vasprintf.c
+++ b/lib/c-vasprintf.c
@@ -2,16 +2,16 @@
Copyright (C) 1999, 2002, 2006-2024 Free Software Foundation, Inc.
This file 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.
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -21,6 +21,7 @@
#include <errno.h>
#include <limits.h>
+#include <stdint.h>
#include <stdlib.h>
#include "c-vasnprintf.h"
@@ -33,12 +34,21 @@ c_vasprintf (char **resultp, const char *format, va_list args)
if (result == NULL)
return -1;
+#if PTRDIFF_MAX > INT_MAX
if (length > INT_MAX)
{
free (result);
- errno = EOVERFLOW;
+ errno = (length > PTRDIFF_MAX ? ENOMEM : EOVERFLOW);
return -1;
}
+#else
+ if (length > PTRDIFF_MAX)
+ {
+ free (result);
+ errno = ENOMEM;
+ return -1;
+ }
+#endif
*resultp = result;
/* Return the number of resulting bytes, excluding the trailing NUL. */
diff --git a/lib/c-vasprintf.h b/lib/c-vasprintf.h
index 7eae757e3a..bcd40bd5e0 100644
--- a/lib/c-vasprintf.h
+++ b/lib/c-vasprintf.h
@@ -52,9 +52,13 @@ ptrdiff_t c_azsprintf (char **resultp, const char *format, ...)
ptrdiff_t c_vazsprintf (char **resultp, const char *format, va_list args)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 2, 0));
-/* asprintf() and vasprintf(), but formatting takes place in the C locale, that
- is, the decimal point used in floating-point formatting directives is always
- '.'. */
+/* Prints formatted output to a string dynamically allocated with malloc().
+ If the memory allocation succeeds, it stores the address of the string in
+ *RESULT and returns the number of resulting bytes, excluding the trailing
+ NUL. Upon memory allocation error, or some other error, it returns -1.
+
+ 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 ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 2, 3));
int c_vasprintf (char **resultp, const char *format, va_list args)
diff --git a/modules/c-vasprintf b/modules/c-vasprintf
index 868dc16d10..8b012daabe 100644
--- a/modules/c-vasprintf
+++ b/modules/c-vasprintf
@@ -7,6 +7,7 @@ lib/c-asprintf.c
lib/c-vasprintf.c
Depends-on:
+stdint
stdio
c-vasnprintf
@@ -19,7 +20,7 @@ Include:
"c-vasprintf.h"
License:
-GPL
+LGPLv2+
Maintainer:
Ben Pfaff
--
2.34.1
>From f7c9406a0166b76a1d9e22e349613025facf5dec Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 22 Jun 2024 12:22:12 +0200
Subject: [PATCH 7/7] c-xvasprintf: Guarantee a non-NULL result.
* lib/c-xvasprintf.h: Clarify the programmer's responsibilities.
(c_xasprintf, c_xvasprintf): Declare as returning non-NULL.
* lib/c-xvasprintf.c: Include <stdlib.h>, <string.h>.
(c_xvasprintf): Call c_vazsprintf instead of c_vasprintf. When some
other error occurs, emit an error message and abort.
* modules/c-xvasprintf (Files): Add m4/strerrorname_np.m4.
(Depends-on): Add extensions, c-vazsprintf. Remove c-vasprintf.
(configure.ac): Invoke gl_OPTIONAL_STRERRORNAME_NP.
* NEWS: Mention the change.
---
ChangeLog | 13 +++++++++++++
NEWS | 2 +-
lib/c-xvasprintf.c | 33 +++++++++++++++++++++++++++++++--
lib/c-xvasprintf.h | 25 +++++++++++++++++--------
modules/c-xvasprintf | 7 +++++--
5 files changed, 67 insertions(+), 13 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f3aec5b928..f81ae03de7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-06-22 Bruno Haible <[email protected]>
+
+ c-xvasprintf: Guarantee a non-NULL result.
+ * lib/c-xvasprintf.h: Clarify the programmer's responsibilities.
+ (c_xasprintf, c_xvasprintf): Declare as returning non-NULL.
+ * lib/c-xvasprintf.c: Include <stdlib.h>, <string.h>.
+ (c_xvasprintf): Call c_vazsprintf instead of c_vasprintf. When some
+ other error occurs, emit an error message and abort.
+ * modules/c-xvasprintf (Files): Add m4/strerrorname_np.m4.
+ (Depends-on): Add extensions, c-vazsprintf. Remove c-vasprintf.
+ (configure.ac): Invoke gl_OPTIONAL_STRERRORNAME_NP.
+ * NEWS: Mention the change.
+
2024-06-22 Bruno Haible <[email protected]>
c-vasprintf: Make return convention consistent with other modules.
diff --git a/NEWS b/NEWS
index 36ffbb64f8..4c5d9fc5de 100644
--- a/NEWS
+++ b/NEWS
@@ -75,7 +75,7 @@ User visible incompatible changes
Date Modules Changes
2024-06-22 xvasprintf It is now the programmer's responsibility to pass
- a valid format string without %ls, %lc directives
+ c-xvasprintf a valid format string without %ls, %lc directives
and that all widths are >= -INT_MAX and <= INT_MAX.
2024-05-16 putenv This module is renamed to 'putenv-gnu'.
diff --git a/lib/c-xvasprintf.c b/lib/c-xvasprintf.c
index 0fda230eb9..b058bde4c5 100644
--- a/lib/c-xvasprintf.c
+++ b/lib/c-xvasprintf.c
@@ -21,6 +21,8 @@
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "c-vasprintf.h"
#include "xalloc.h"
@@ -30,11 +32,38 @@ c_xvasprintf (const char *format, va_list args)
{
char *result;
- if (c_vasprintf (&result, format, args) < 0)
+ if (c_vazsprintf (&result, format, args) < 0)
{
if (errno == ENOMEM)
xalloc_die ();
- return NULL;
+ else
+ {
+ /* The programmer ought to have ensured that none of the other errors
+ can occur. */
+ int err = errno;
+ char errbuf[20];
+ const char *errname;
+#if HAVE_WORKING_STRERRORNAME_NP
+ errname = strerrorname_np (err);
+ if (errname == NULL)
+#else
+ if (err == EINVAL)
+ errname = "EINVAL";
+ else if (err == EILSEQ)
+ errname = "EILSEQ";
+ else if (err == EOVERFLOW)
+ errname = "EOVERFLOW";
+ else
+#endif
+ {
+ sprintf (errbuf, "%d", err);
+ errname = errbuf;
+ }
+ fprintf (stderr, "c_vasprintf failed! format=\"%s\", errno=%s\n",
+ format, errname);
+ fflush (stderr);
+ abort ();
+ }
}
return result;
diff --git a/lib/c-xvasprintf.h b/lib/c-xvasprintf.h
index 4cb4578584..897ecfdbf2 100644
--- a/lib/c-xvasprintf.h
+++ b/lib/c-xvasprintf.h
@@ -17,7 +17,8 @@
#ifndef _C_XVASPRINTF_H
#define _C_XVASPRINTF_H
-/* This file uses _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_MALLOC. */
+/* This file uses _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_MALLOC,
+ _GL_ATTRIBUTE_RETURNS_NONNULL. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
@@ -34,22 +35,30 @@
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,
+/* Prints formatted output to a string dynamically allocated with malloc(),
+ and returns it. Upon [ENOMEM] memory allocation error, it calls xalloc_die.
+
+ It is the responsibility of the programmer to ensure that
+ - the format string is valid,
+ - the format string does not use %ls or %lc directives, and
+ - all widths in the format string and passed as arguments are >= -INT_MAX
+ and <= INT_MAX,
+ so that other errors
- [EINVAL] invalid format string,
- [EILSEQ] error during conversion between wide and multibyte characters,
- return NULL.
+ - [EOVERFLOW] some specified width is > INT_MAX,
+ cannot occur.
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 ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 1, 2))
- _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
+ _GL_ATTRIBUTE_RETURNS_NONNULL;
extern char *c_xvasprintf (const char *format, va_list args)
_GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 1, 0))
- _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
+ _GL_ATTRIBUTE_RETURNS_NONNULL;
#ifdef __cplusplus
}
diff --git a/modules/c-xvasprintf b/modules/c-xvasprintf
index b952128fb6..ccbc93d794 100644
--- a/modules/c-xvasprintf
+++ b/modules/c-xvasprintf
@@ -5,13 +5,16 @@ Files:
lib/c-xvasprintf.h
lib/c-xasprintf.c
lib/c-xvasprintf.c
+m4/strerrorname_np.m4
Depends-on:
+extensions
stdio
-c-vasprintf
+c-vazsprintf
xalloc-die
configure.ac:
+gl_OPTIONAL_STRERRORNAME_NP
Makefile.am:
lib_SOURCES += c-xasprintf.c c-xvasprintf.c
@@ -23,4 +26,4 @@ License:
GPL
Maintainer:
-Ben Pfaff
+all
--
2.34.1