diff options
author | Rafal Luzynski <digitalfreak@lingonborough.com> | 2017-11-14 02:22:38 +0100 |
---|---|---|
committer | Rafal Luzynski <digitalfreak@lingonborough.com> | 2018-01-22 11:26:55 +0100 |
commit | 761a585ce9245d5ad968303b200eef1f26fd501c (patch) | |
tree | eb8b910a79124554a0863d26a4dae85e3cfef4bf /time | |
parent | Implement alternative month names (bug 10871). (diff) | |
download | glibc-761a585ce9245d5ad968303b200eef1f26fd501c.tar.gz glibc-761a585ce9245d5ad968303b200eef1f26fd501c.tar.bz2 glibc-761a585ce9245d5ad968303b200eef1f26fd501c.zip |
Abbreviated alternative month names (%Ob) also added (bug 10871).
All the previous changes also repeated to support abbreviated
alternative month names. In most languages which have declension and
need nominative/genitive month names the abbreviated forms for both
cases are the same. An example where they do differ is May in Russian:
this name is too short to be abbreviated so even the abbreviated form
features the declension suffixes.
[BZ #10871]
* locale/C-time.c (_nl_C_LC_TIME): Add abbreviated alternative month
names, define them as the same as abbreviated month names explicitly.
* locale/categories.def (LC_TIME): Add ab_alt_mon and wide-ab_alt_mon.
* locale/langinfo.h: (_NL_ABALTMON_1, _NL_ABALTMON_2, _NL_ABALTMON_3,
_NL_ABALTMON_4, _NL_ABALTMON_5, _NL_ABALTMON_6, _NL_ABALTMON_7,
_NL_ABALTMON_8, _NL_ABALTMON_9, _NL_ABALTMON_10, _NL_ABALTMON_11,
_NL_ABALTMON_12, _NL_WABALTMON_1, _NL_WABALTMON_2, _NL_WABALTMON_3,
_NL_WABALTMON_4, _NL_WABALTMON_5, _NL_WABALTMON_6, _NL_WABALTMON_7,
_NL_WABALTMON_8, _NL_WABALTMON_9, _NL_WABALTMON_10, _NL_WABALTMON_11,
_NL_WABALTMON_12): New enum constants.
* locale/programs/ld-time.c (struct locale_time_t): Add ab_alt_mon,
wab_alt_mon, and ab_alt_mon_defined members.
(time_output): Output ab_alt_mon and wab_alt_mon members.
(time_read): Read them, initialize them as copies of abmon and wabmon
respectively if they are missing, initialize ab_alt_mon_defined.
* locale/programs/locfile-kw.gperf (ab_alt_mon): Define.
* locale/programs/locfile-kw.h: Regenerate.
* locale/programs/locfile-token.h (tok_ab_alt_mon): New enum constant.
* time/Makefile [$(run-built-tests) = yes] (LOCALES): Add es_ES.UTF-8
and ru_RU.UTF-8.
* time/strftime_l.c (a_altmonth, aam_len): New macros.
[!COMPILE_WIDE] (ABALTMON_1): New macro.
(__strftime_internal): Handle %Ob and %Oh formats.
* time/strptime_l.c [_LIBC] (ab_alt_month_name): New macro.
(__strptime_internal): Handle %Ob and %Oh formats.
* time/tst-strptime.c (day_tests): Add more tests to parse different
forms of month names including the new %Ob format specifier.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'time')
-rw-r--r-- | time/Makefile | 2 | ||||
-rw-r--r-- | time/strftime_l.c | 14 | ||||
-rw-r--r-- | time/strptime_l.c | 18 | ||||
-rw-r--r-- | time/tst-strptime.c | 9 |
4 files changed, 40 insertions, 3 deletions
diff --git a/time/Makefile b/time/Makefile index 2deb025013..0db1206820 100644 --- a/time/Makefile +++ b/time/Makefile @@ -49,7 +49,7 @@ include ../Rules ifeq ($(run-built-tests),yes) LOCALES := de_DE.ISO-8859-1 en_US.ISO-8859-1 ja_JP.EUC-JP fr_FR.UTF-8 \ - pl_PL.UTF-8 + es_ES.UTF-8 pl_PL.UTF-8 ru_RU.UTF-8 include ../gen-locales.mk $(objpfx)tst-ftime_l.out: $(gen-locales) diff --git a/time/strftime_l.c b/time/strftime_l.c index ac5d28fbcc..c71f9f47a9 100644 --- a/time/strftime_l.c +++ b/time/strftime_l.c @@ -106,6 +106,7 @@ extern char *tzname[]; # define UCHAR_T unsigned char # define L_(Str) Str # define NLW(Sym) Sym +# define ABALTMON_1 _NL_ABALTMON_1 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY # define MEMCPY(d, s, n) bcopy ((s), (d), (n)) @@ -492,6 +493,9 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, # define f_month \ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) +# define a_altmonth \ + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon))) # define f_altmonth \ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon))) @@ -501,6 +505,7 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, # define aw_len STRLEN (a_wkday) # define am_len STRLEN (a_month) +# define aam_len STRLEN (a_altmonth) # define ap_len STRLEN (ampm) #else # if !HAVE_STRFTIME @@ -510,11 +515,13 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, ? "?" : month_name[tp->tm_mon]) # define a_wkday f_wkday # define a_month f_month +# define a_altmonth a_month # define f_altmonth f_month # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) size_t aw_len = 3; size_t am_len = 3; + size_t aam_len = 3; size_t ap_len = 2; # endif #endif @@ -779,10 +786,13 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format, to_uppcase = 1; to_lowcase = 0; } - if (modifier != 0) + if (modifier == L_('E')) goto bad_format; #if defined _NL_CURRENT || !HAVE_STRFTIME - cpy (am_len, a_month); + if (modifier == L_('O')) + cpy (aam_len, a_altmonth); + else + cpy (am_len, a_month); break; #else goto underlying_strftime; diff --git a/time/strptime_l.c b/time/strptime_l.c index 39cf38d9a9..cd901c2606 100644 --- a/time/strptime_l.c +++ b/time/strptime_l.c @@ -126,6 +126,8 @@ extern const struct __locale_data _nl_C_LC_TIME attribute_hidden; # define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string) # define alt_month_name \ (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ALTMON_1)].string) +# define ab_alt_month_name \ + (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (_NL_ABALTMON_1)].string) # define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string) # define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string) # define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string) @@ -437,6 +439,18 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp, alt_month_name[cnt])) decided_longest = loc; } + trp = rp; + if (match_string (_NL_CURRENT (LC_TIME, _NL_ABALTMON_1 + cnt), + trp) + && trp > rp_longest) + { + rp_longest = trp; + cnt_longest = cnt; + if (s.decided == not + && strcmp (_NL_CURRENT (LC_TIME, _NL_ABALTMON_1 + cnt), + alt_month_name[cnt])) + decided_longest = loc; + } #endif } #endif @@ -448,6 +462,8 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp, #ifdef _LIBC || ((trp = rp, match_string (alt_month_name[cnt], trp)) && trp > rp_longest) + || ((trp = rp, match_string (ab_alt_month_name[cnt], trp)) + && trp > rp_longest) #endif )) { @@ -1035,7 +1051,9 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp, case 'O': switch (*fmt++) { + case 'b': case 'B': + case 'h': /* Match month name. Reprocess as plain 'B'. */ fmt--; goto start_over; diff --git a/time/tst-strptime.c b/time/tst-strptime.c index 62ecb7c804..2eac5a25cb 100644 --- a/time/tst-strptime.c +++ b/time/tst-strptime.c @@ -56,6 +56,7 @@ static const struct { "en_US.ISO-8859-1", "November 17, 2017", "%B %e, %Y", 5, 320, 10, 17 }, { "de_DE.ISO-8859-1", "18. Nov 2017", "%d. %b %Y", 6, 321, 10, 18 }, { "fr_FR.UTF-8", "19 novembre 2017", "%d %OB %Y", 0, 322, 10, 19 }, + { "es_ES.UTF-8", "20 de nov de 2017", "%d de %Ob de %Y", 1, 323, 10, 20 }, /* Some languages do need the declension of the month names. */ { "pl_PL.UTF-8", "21 lis 2017", "%d %b %Y", 2, 324, 10, 21 }, { "pl_PL.UTF-8", "22 LIS 2017", "%d %B %Y", 3, 325, 10, 22 }, @@ -63,6 +64,14 @@ static const struct { "pl_PL.UTF-8", "23 listopad 2017", "%d %B %Y", 4, 326, 10, 23 }, /* The nominative case is incorrect here but it is parseable. */ { "pl_PL.UTF-8", "24 listopad 2017", "%d %OB %Y", 5, 327, 10, 24 }, + { "pl_PL.UTF-8", "25 lis 2017", "%d %Ob %Y", 6, 328, 10, 25 }, + /* ноя - pronounce: 'noya' - "Nov" (abbreviated "November") in Russian. */ + { "ru_RU.UTF-8", "26 ноя 2017", "%d %b %Y", 0, 329, 10, 26 }, + /* TODO: Add an example of "may"/"maya" (5th month, May) using %Ob in + Russian when the localedata is updated. Without the genitive forms + in localedata the word "maya" is ambiguous and may be mistaken for + "mart" (March). + */ }; |