summaryrefslogtreecommitdiff
path: root/lib/nstrftime.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-12-06 15:16:15 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2019-12-06 15:17:08 -0800
commitc4cd2a0b9f251ed830ef32ac6537e62ae5e3d944 (patch)
tree25aec8ec7432bae87fd6b38f06a6d191d96151c4 /lib/nstrftime.c
parent99ad65eda44e3b6edcc51cf0fb70ea499c3ccb07 (diff)
downloademacs-c4cd2a0b9f251ed830ef32ac6537e62ae5e3d944.tar.gz
Update from Gnulib
This incorporates: 2019-12-06 nstrftime: better width support for %N, %z 2019-12-03 Avoid hassles caused by [[noreturn]] in C++ 2019-12-02 Fix mistakes in --enable-threads=isoc fixes from 2019-12-01 * admin/merge-gnulib (AVOIDED_MODULES): Avoid pthread-h. * lib/_Noreturn.h, lib/nstrftime.c, m4/gnulib-common.m4: * m4/timer_time.m4: Copy from Gnulib. * lib/gnulib.mk.in: Regenerate.
Diffstat (limited to 'lib/nstrftime.c')
-rw-r--r--lib/nstrftime.c138
1 files changed, 59 insertions, 79 deletions
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index 461dadb2929..4eae1dc4ebb 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -162,19 +162,20 @@ extern char *tzname[];
# define advance(P, N) ((P) += (N))
#endif
-#define add(n, f) \
+#define add(n, f) width_add (width, n, f)
+#define width_add(width, n, f) \
do \
{ \
size_t _n = (n); \
- size_t _w = (width < 0 ? 0 : width); \
+ size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
size_t _incr = _n < _w ? _w : _n; \
if (_incr >= maxsize - i) \
return 0; \
if (p) \
{ \
- if (digits == 0 && _n < _w) \
+ if (_n < _w) \
{ \
- size_t _delta = width - _n; \
+ size_t _delta = _w - _n; \
if (pad == L_('0') || pad == L_('+')) \
memset_zero (p, _delta); \
else \
@@ -186,15 +187,17 @@ extern char *tzname[];
i += _incr; \
} while (0)
+#define add1(c) width_add1 (width, c)
#if FPRINTFTIME
-# define add1(C) add (1, fputc (C, p))
+# define width_add1(width, c) width_add (width, 1, fputc (c, p))
#else
-# define add1(C) add (1, *p = C)
+# define width_add1(width, c) width_add (width, 1, *p = c)
#endif
+#define cpy(n, s) width_cpy (width, n, s)
#if FPRINTFTIME
-# define cpy(n, s) \
- add ((n), \
+# define width_cpy(width, n, s) \
+ width_add (width, n, \
do \
{ \
if (to_lowcase) \
@@ -214,8 +217,8 @@ extern char *tzname[];
while (0) \
)
#else
-# define cpy(n, s) \
- add ((n), \
+# define width_cpy(width, n, s) \
+ width_add (width, n, \
if (to_lowcase) \
memcpy_lowcase (p, (s), _n LOCALE_ARG); \
else if (to_uppcase) \
@@ -435,9 +438,10 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
libc_hidden_def (my_strftime)
#endif
-/* Just like my_strftime, above, but with two more parameters.
- UPCASE indicate that the result should be converted to upper case,
- and *TZSET_CALLED indicates whether tzset has been called here. */
+/* Just like my_strftime, above, but with more parameters.
+ UPCASE indicates that the result should be converted to upper case.
+ YR_SPEC and WIDTH specify the padding and width for the year.
+ *TZSET_CALLED indicates whether tzset has been called here. */
static size_t
__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
const CHAR_T *format,
@@ -556,7 +560,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
for (f = format; *f != '\0'; width = -1, f++)
{
- int pad = 0; /* Padding for number ('-', '_', or 0). */
+ int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */
int modifier; /* Field modifier ('E', 'O', or 0). */
int digits = 0; /* Max digits for numeric format. */
int number_value; /* Numeric value to be printed. */
@@ -565,7 +569,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
bool always_output_a_sign; /* +/- should always be output. */
int tz_colon_mask; /* Bitmask of where ':' should appear. */
const CHAR_T *subfmt;
- CHAR_T sign_char;
CHAR_T *bufp;
CHAR_T buf[1
+ 2 /* for the two colons in a %::z or %:::z time zone */
@@ -1035,59 +1038,34 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
while (u_number_value != 0 || tz_colon_mask != 0);
do_number_sign_and_padding:
- if (digits < width)
- digits = width;
-
- sign_char = (negative_number ? L_('-')
- : always_output_a_sign ? L_('+')
- : 0);
-
- if (pad == L_('-'))
- {
- if (sign_char)
- add1 (sign_char);
- }
- else
- {
- int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
- - bufp) - !!sign_char;
-
- if (padding > 0)
- {
- if (pad == L_('_'))
- {
- if ((size_t) padding >= maxsize - i)
- return 0;
-
- if (p)
- memset_space (p, padding);
- i += padding;
- width = width > padding ? width - padding : 0;
- if (sign_char)
- add1 (sign_char);
- }
- else
- {
- if ((size_t) digits >= maxsize - i)
- return 0;
-
- if (sign_char)
- add1 (sign_char);
+ if (pad == 0)
+ pad = L_('0');
+ if (width < 0)
+ width = digits;
- if (p)
- memset_zero (p, padding);
- i += padding;
- width = 0;
- }
- }
- else
- {
- if (sign_char)
- add1 (sign_char);
- }
- }
+ {
+ CHAR_T sign_char = (negative_number ? L_('-')
+ : always_output_a_sign ? L_('+')
+ : 0);
+ int numlen = buf + sizeof buf / sizeof buf[0] - bufp;
+ int shortage = width - !!sign_char - numlen;
+ int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage;
+
+ if (sign_char)
+ {
+ if (pad == L_('_'))
+ {
+ if (p)
+ memset_space (p, padding);
+ i += padding;
+ width -= padding;
+ }
+ width_add1 (0, sign_char);
+ width--;
+ }
- cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
+ cpy (numlen, bufp);
+ }
break;
case L_('F'):
@@ -1153,19 +1131,21 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('N'): /* GNU extension. */
if (modifier == L_('E'))
goto bad_format;
-
- number_value = ns;
- if (width == -1)
- width = 9;
- else
- {
- /* Take an explicit width less than 9 as a precision. */
- int j;
- for (j = width; j < 9; j++)
- number_value /= 10;
- }
-
- DO_NUMBER (width, number_value);
+ {
+ int n = ns, ns_digits = 9;
+ if (width <= 0)
+ width = ns_digits;
+ int ndigs = ns_digits;
+ while (width < ndigs || (1 < ndigs && n % 10 == 0))
+ ndigs--, n /= 10;
+ for (int i = ndigs; 0 < i; i--)
+ buf[i - 1] = n % 10 + L_('0'), n /= 10;
+ if (!pad)
+ pad = L_('0');
+ width_cpy (0, ndigs, buf);
+ width_add (width - ndigs, 0, (void) 0);
+ }
+ break;
#endif
case L_('n'):