From: Paul Eggert <eggert@cs.ucla.edu>
To: bug-gnulib@gnu.org
Cc: Paul Eggert <eggert@cs.ucla.edu>
Subject: [PATCH] nstrftime: support the ‘+’ flag
Date: Sun, 24 Feb 2019 23:33:10 -0800 [thread overview]
Message-ID: <20190225073310.9678-1-eggert@cs.ucla.edu> (raw)
* lib/nstrftime.c (add, __strftime_internal):
Add support for the ‘+’ flag introduced in POSIX.1-2017.
(__strftime_internal): New arg ‘width’. All uses changed.
(DO_YEARISH, DO_MAYBE_SIGNED_NUMBER): New macros.
---
ChangeLog | 8 +++++
lib/nstrftime.c | 84 ++++++++++++++++++++++++++++++++-----------------
2 files changed, 64 insertions(+), 28 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1f4205582..4fe487749 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2019-02-24 Paul Eggert <eggert@cs.ucla.edu>
+
+ nstrftime: support the ‘+’ flag
+ * lib/nstrftime.c (add, __strftime_internal):
+ Add support for the ‘+’ flag introduced in POSIX.1-2017.
+ (__strftime_internal): New arg ‘width’. All uses changed.
+ (DO_YEARISH, DO_MAYBE_SIGNED_NUMBER): New macros.
+
2019-02-24 Bruno Haible <bruno@clisp.org>
relocatable-prog: Improve verbose output.
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index 424fb6069..01db02bfe 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -180,7 +180,7 @@ extern char *tzname[];
if (digits == 0 && _n < _w) \
{ \
size_t _delta = width - _n; \
- if (pad == L_('0')) \
+ if (pad == L_('0') || pad == L_('+')) \
memset_zero (p, _delta); \
else \
memset_space (p, _delta); \
@@ -418,7 +418,7 @@ iso_week_days (int yday, int wday)
static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
const CHAR_T *, const struct tm *,
- bool, int, bool *
+ bool, int, int, bool *
extra_args_spec LOCALE_PARAM);
/* Write information from TP into S according to the format
@@ -434,7 +434,7 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
{
bool tzset_called = false;
return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false,
- 0, &tzset_called extra_args LOCALE_ARG);
+ 0, -1, &tzset_called extra_args LOCALE_ARG);
}
#if defined _LIBC && ! FPRINTFTIME
libc_hidden_def (my_strftime)
@@ -447,7 +447,7 @@ static size_t
__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
const CHAR_T *format,
const struct tm *tp, bool upcase,
- int yr_spec, bool *tzset_called
+ int yr_spec, int width, bool *tzset_called
extra_args_spec LOCALE_PARAM)
{
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
@@ -559,7 +559,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (hour12 == 0)
hour12 = 12;
- for (f = format; *f != '\0'; ++f)
+ for (f = format; *f != '\0'; width = -1, f++)
{
int pad = 0; /* Padding for number ('-', '_', or 0). */
int modifier; /* Field modifier ('E', 'O', or 0). */
@@ -577,12 +577,12 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
+ (sizeof (int) < sizeof (time_t)
? INT_STRLEN_BOUND (time_t)
: INT_STRLEN_BOUND (int))];
- int width = -1;
bool to_lowcase = false;
bool to_uppcase = upcase;
size_t colons;
bool change_case = false;
int format_char;
+ int subwidth;
#if DO_MULTIBYTE && !defined COMPILE_WIDE
switch (*f)
@@ -680,6 +680,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
/* This influences the number formats. */
case L_('_'):
case L_('-'):
+ case L_('+'):
case L_('0'):
pad = *f;
continue;
@@ -698,7 +699,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
break;
}
- /* As a GNU extension we allow the field width to be specified. */
if (ISDIGIT (*f))
{
width = 0;
@@ -744,12 +744,16 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
} \
while (0)
#define DO_SIGNED_NUMBER(d, negative, v) \
+ DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
+#define DO_YEARISH(d, negative, v) \
+ DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
+#define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
do \
{ \
digits = d; \
negative_number = negative; \
u_number_value = v; \
- goto do_signed_number; \
+ goto label; \
} \
while (0)
@@ -862,15 +866,17 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
#endif
subformat:
+ subwidth = -1;
+ subformat_width:
{
size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
subfmt, tp, to_uppcase,
- yr_spec, tzset_called
+ pad, subwidth, tzset_called
extra_args LOCALE_ARG);
add (len, __strftime_internal (p,
STRFTIME_ARG (maxsize - i)
subfmt, tp, to_uppcase,
- yr_spec, tzset_called
+ pad, subwidth, tzset_called
extra_args LOCALE_ARG));
}
break;
@@ -931,7 +937,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
{
int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
century -= tp->tm_year % 100 < 0 && 0 < century;
- DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
+ DO_YEARISH (2, tp->tm_year < - TM_YEAR_BASE, century);
}
case L_('x'):
@@ -972,9 +978,17 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
always_output_a_sign = true;
goto do_number_body;
+ do_yearish:
+ if (pad == 0)
+ pad = yr_spec;
+ always_output_a_sign
+ = (pad == L_('+')
+ && ((digits == 2 ? 99 : 9999) < u_number_value
+ || digits < width));
+ goto do_maybe_signed_number;
+
do_number_spacepad:
- /* Force '_' flag unless overridden by '0' or '-' flag. */
- if (pad != L_('0') && pad != L_('-'))
+ if (pad == 0)
pad = L_('_');
do_number:
@@ -984,6 +998,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
do_signed_number:
always_output_a_sign = false;
+
+ do_maybe_signed_number:
tz_colon_mask = 0;
do_number_body:
@@ -1088,8 +1104,19 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('F'):
if (modifier != 0)
goto bad_format;
+ if (pad == 0 && width < 0)
+ {
+ pad = L_('+');
+ subwidth = 4;
+ }
+ else
+ {
+ subwidth = width - 6;
+ if (subwidth < 0)
+ subwidth = 0;
+ }
subfmt = L_("%Y-%m-%d");
- goto subformat;
+ goto subformat_width;
case L_('H'):
if (modifier == L_('E'))
@@ -1298,17 +1325,18 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('g'):
{
int yy = (tp->tm_year % 100 + year_adjust) % 100;
- DO_NUMBER (2, (0 <= yy
- ? yy
- : tp->tm_year < -TM_YEAR_BASE - year_adjust
- ? -yy
- : yy + 100));
+ DO_YEARISH (2, false,
+ (0 <= yy
+ ? yy
+ : tp->tm_year < -TM_YEAR_BASE - year_adjust
+ ? -yy
+ : yy + 100));
}
case L_('G'):
- DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
- (tp->tm_year + (unsigned int) TM_YEAR_BASE
- + year_adjust));
+ DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
+ (tp->tm_year + (unsigned int) TM_YEAR_BASE
+ + year_adjust));
default:
DO_NUMBER (2, days / 7 + 1);
@@ -1339,8 +1367,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
# else
subfmt = era->era_format;
# endif
- if (pad != 0)
- yr_spec = pad;
+ if (pad == 0)
+ pad = yr_spec;
goto subformat;
}
#else
@@ -1350,8 +1378,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (modifier == L_('O'))
goto bad_format;
- DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
- tp->tm_year + (unsigned int) TM_YEAR_BASE);
+ DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
+ tp->tm_year + (unsigned int) TM_YEAR_BASE);
case L_('y'):
if (modifier == L_('E'))
@@ -1361,7 +1389,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (era)
{
int delta = tp->tm_year - era->start_date[0];
- if (yr_spec != 0)
+ if (pad == 0)
pad = yr_spec;
DO_NUMBER (2, (era->offset
+ delta * era->absolute_direction));
@@ -1375,7 +1403,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
int yy = tp->tm_year % 100;
if (yy < 0)
yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
- DO_NUMBER (2, yy);
+ DO_YEARISH (2, false, yy);
}
case L_('Z'):
--
2.20.1
reply other threads:[~2019-02-25 7:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190225073310.9678-1-eggert@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=bug-gnulib@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).