]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - locale/programs/ld-time.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / locale / programs / ld-time.c
index 9ec58f6487e40cf967233c4347f914362b84083f..a1721e05c6f5838b45cab70d3a966a7aec391d3d 100644 (file)
@@ -1,21 +1,19 @@
-/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   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; version 2 of the License, or
+   (at your option) any later version.
 
-   The GNU C Library is distributed in the hope that it will be useful,
+   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
-   Library General Public License for more details.
+   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 Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#include <stdint.h>
 #include <sys/uio.h>
 
 #include <assert.h>
 
-#include "linereader.h"
 #include "localedef.h"
+#include "linereader.h"
 #include "localeinfo.h"
 #include "locfile.h"
 
@@ -89,7 +88,15 @@ struct locale_time_t
   const uint32_t *wera_d_fmt;
   const char *alt_digits[100];
   const uint32_t *walt_digits[100];
+  const char *date_fmt;
+  const uint32_t *wdate_fmt;
   int alt_digits_defined;
+  const char *alt_mon[12];
+  const uint32_t *walt_mon[12];
+  int alt_mon_defined;
+  const char *ab_alt_mon[12];
+  const uint32_t *wab_alt_mon[12];
+  int ab_alt_mon_defined;
   unsigned char week_ndays;
   uint32_t week_1stday;
   unsigned char week_1stweek;
@@ -115,7 +122,7 @@ time_startup (struct linereader *lr, struct localedef_t *locale,
     locale->categories[LC_TIME].time =
       (struct locale_time_t *) xcalloc (1, sizeof (struct locale_time_t));
 
-  if (time != NULL)
+  if (lr != NULL)
     {
       lr->translate_strings = 1;
       lr->return_widestr = 1;
@@ -124,7 +131,7 @@ time_startup (struct linereader *lr, struct localedef_t *locale,
 
 
 void
-time_finish (struct localedef_t *locale, struct charmap_t *charmap)
+time_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 {
   struct locale_time_t *time = locale->categories[LC_TIME].time;
   int nothing = 0;
@@ -154,44 +161,68 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
         empty one.  */
       if (time == NULL)
        {
-         error (0, 0, _("No definition for %s category found"), "LC_TIME");
+         record_warning (_("\
+No definition for %s category found"), "LC_TIME");
          time_startup (NULL, locale, 0);
          time = locale->categories[LC_TIME].time;
          nothing = 1;
        }
     }
 
-#define TESTARR_ELEM(cat) \
+#define noparen(arg1, argn...) arg1, ##argn
+#define TESTARR_ELEM(cat, val) \
   if (!time->cat##_defined)                                                  \
     {                                                                        \
-      if(! be_quiet && ! nothing)                                            \
-       error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);       \
+      const char *initval[] = { noparen val };                               \
+      unsigned int i;                                                        \
+                                                                             \
+      if (! nothing)                                                         \
+       record_error (0, 0, _("%s: field `%s' not defined"),                  \
+                     "LC_TIME", #cat);                                       \
+                                                                             \
+      for (i = 0; i < sizeof (initval) / sizeof (initval[0]); ++i)           \
+       time->cat[i] = initval[i];                                            \
     }
 
-  TESTARR_ELEM (abday);
-  TESTARR_ELEM (day);
-  TESTARR_ELEM (abmon);
-  TESTARR_ELEM (mon);
-  TESTARR_ELEM (am_pm);
-
-#define TEST_ELEM(cat) \
+  TESTARR_ELEM (abday, ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ));
+  TESTARR_ELEM (day, ( "Sunday", "Monday", "Tuesday", "Wednesday",
+                       "Thursday", "Friday", "Saturday" ));
+  TESTARR_ELEM (abmon, ( "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ));
+  TESTARR_ELEM (mon, ( "January", "February", "March", "April",
+                       "May", "June", "July", "August",
+                       "September", "October", "November", "December" ));
+  TESTARR_ELEM (am_pm, ( "AM", "PM" ));
+
+#define TEST_ELEM(cat, initval) \
   if (time->cat == NULL)                                                     \
     {                                                                        \
-      if (! be_quiet && ! nothing)                                           \
-       error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);       \
+      if (! nothing)                                                         \
+       record_error (0, 0, _("%s: field `%s' not defined"),                  \
+                     "LC_TIME", #cat);                                       \
+                                                                             \
+      time->cat = initval;                                                   \
     }
 
-  TEST_ELEM (d_t_fmt);
-  TEST_ELEM (d_fmt);
-  TEST_ELEM (t_fmt);
+  TEST_ELEM (d_t_fmt, "%a %b %e %H:%M:%S %Y");
+  TEST_ELEM (d_fmt, "%m/%d/%y");
+  TEST_ELEM (t_fmt, "%H:%M:%S");
 
   /* According to C.Y.Alexis Cheng <alexis@vnet.ibm.com> the T_FMT_AMPM
      field is optional.  */
   if (time->t_fmt_ampm == NULL)
     {
-      /* Use the 24h format as default.  */
-      time->t_fmt_ampm = time->t_fmt;
-      time->wt_fmt_ampm = time->wt_fmt;
+      if (time->am_pm[0][0] == '\0' && time->am_pm[1][0] == '\0')
+       {
+         /* No AM/PM strings defined, use the 24h format as default.  */
+         time->t_fmt_ampm = time->t_fmt;
+         time->wt_fmt_ampm = time->wt_fmt;
+       }
+      else
+       {
+         time->t_fmt_ampm = "%I:%M:%S %p";
+         time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p";
+       }
     }
 
   /* Now process the era entries.  */
@@ -217,10 +248,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          /* First character must be + or - for the direction.  */
          if (*str != '+' && *str != '-')
            {
-             if (!be_quiet)
-               error (0, 0, _("%s: direction flag in string %d in `era' field"
-                              " is not '+' nor '-'"),
-                      "LC_TIME", idx + 1);
+             record_error (0, 0, _("\
+%s: direction flag in string %Zd in `era' field is not '+' nor '-'"),
+                           "LC_TIME", idx + 1);
              /* Default arbitrarily to '+'.  */
              time->era_entries[idx].direction = '+';
            }
@@ -228,10 +258,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
            time->era_entries[idx].direction = *str;
          if (*++str != ':')
            {
-             if (!be_quiet)
-               error (0, 0, _("%s: direction flag in string %d in `era' field"
-                              " is not a single character"),
-                      "LC_TIME", idx + 1);
+             record_error (0, 0, _("\
+%s: direction flag in string %Zd in `era' field is not a single character"),
+                           "LC_TIME", idx + 1);
              (void) strsep (&str, ":");
            }
          else
@@ -241,18 +270,16 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          time->era_entries[idx].offset = strtol (str, &endp, 10);
          if (endp == str)
            {
-             if (!be_quiet)
-               error (0, 0, _("%s: invalid number for offset in string %d in"
-                              " `era' field"),
-                      "LC_TIME", idx + 1);
+             record_error (0, 0, _("\
+%s: invalid number for offset in string %Zd in `era' field"),
+                           "LC_TIME", idx + 1);
              (void) strsep (&str, ":");
            }
          else if (*endp != ':')
            {
-             if (!be_quiet)
-               error (0, 0, _("%s: garbage at end of offset value in"
-                              " string %d in `era' field"),
-                      "LC_TIME", idx + 1);
+             record_error (0, 0, _("\
+%s: garbage at end of offset value in string %Zd in `era' field"),
+                           "LC_TIME", idx + 1);
              (void) strsep (&str, ":");
            }
          else
@@ -285,6 +312,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
              else
                str = endp + 1;
              time->era_entries[idx].start_date[0] -= 1900;
+             /* year -1 represent 1 B.C. (not -1 A.D.) */
+             if (time->era_entries[idx].start_date[0] < -1900)
+               ++time->era_entries[idx].start_date[0];
 
              time->era_entries[idx].start_date[1] = strtol (str, &endp, 10);
              if (endp == str || *endp != '/')
@@ -297,19 +327,17 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
              if (endp == str)
                {
                invalid_start_date:
-                 if (!be_quiet)
-                   error (0, 0, _("%s: invalid starting date in string %d in"
-                                  " `era' field"),
-                          "LC_TIME", idx + 1);
+                 record_error (0, 0, _("\
+%s: invalid starting date in string %Zd in `era' field"),
+                               "LC_TIME", idx + 1);
                  (void) strsep (&str, ":");
                }
              else if (*endp != ':')
                {
                garbage_start_date:
-                 if (!be_quiet)
-                   error (0, 0, _("%s: garbage at end of starting date "
-                                  "in string %d in `era' field "),
-                          "LC_TIME", idx + 1);
+                 record_error (0, 0, _("\
+%s: garbage at end of starting date in string %Zd in `era' field "),
+                               "LC_TIME", idx + 1);
                  (void) strsep (&str, ":");
                }
              else
@@ -324,11 +352,10 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                           > days_per_month[time->era_entries[idx].start_date[1]])
                       || (time->era_entries[idx].start_date[1] == 2
                           && time->era_entries[idx].start_date[2] == 29
-                          && !__isleap (time->era_entries[idx].start_date[0])))
-                     && !be_quiet)
-                         error (0, 0, _("%s: starting date is invalid in"
-                                        " string %d in `era' field"),
-                                "LC_TIME", idx + 1);
+                          && !__isleap (time->era_entries[idx].start_date[0]))))
+                   record_error (0, 0, _("\
+%s: starting date is invalid in string %Zd in `era' field"),
+                                 "LC_TIME", idx + 1);
                }
            }
 
@@ -359,6 +386,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
              else
                str = endp + 1;
              time->era_entries[idx].stop_date[0] -= 1900;
+             /* year -1 represent 1 B.C. (not -1 A.D.) */
+             if (time->era_entries[idx].stop_date[0] < -1900)
+               ++time->era_entries[idx].stop_date[0];
 
              time->era_entries[idx].stop_date[1] = strtol (str, &endp, 10);
              if (endp == str || *endp != '/')
@@ -371,19 +401,17 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
              if (endp == str)
                {
                invalid_stop_date:
-                 if (!be_quiet)
-                   error (0, 0, _("%s: invalid stopping date in string %d in"
-                                  " `era' field"),
-                          "LC_TIME", idx + 1);
+                 record_error (0, 0, _("\
+%s: invalid stopping date in string %Zd in `era' field"),
+                               "LC_TIME", idx + 1);
                  (void) strsep (&str, ":");
                }
              else if (*endp != ':')
                {
                garbage_stop_date:
-                 if (!be_quiet)
-                   error (0, 0, _("%s: garbage at end of stopping date "
-                                  "in string %d in `era' field"),
-                          "LC_TIME", idx + 1);
+                 record_error (0, 0, _("\
+%s: garbage at end of stopping date in string %Zd in `era' field"),
+                               "LC_TIME", idx + 1);
                  (void) strsep (&str, ":");
                }
              else
@@ -398,19 +426,17 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                           > days_per_month[time->era_entries[idx].stop_date[1]])
                       || (time->era_entries[idx].stop_date[1] == 2
                           && time->era_entries[idx].stop_date[2] == 29
-                          && !__isleap (time->era_entries[idx].stop_date[0])))
-                     && !be_quiet)
-                         error (0, 0, _("%s: stopping date is invalid in"
-                                        " string %d in `era' field"),
-                                "LC_TIME", idx + 1);
+                          && !__isleap (time->era_entries[idx].stop_date[0]))))
+                   record_error (0, 0, _("\
+%s: invalid stopping date in string %Zd in `era' field"),
+                                 "LC_TIME", idx + 1);
                }
            }
 
          if (str == NULL || *str == '\0')
            {
-             if (!be_quiet)
-               error (0, 0, _("%s: missing era name in string %d in `era'"
-                              " field"), "LC_TIME", idx + 1);
+             record_error (0, 0, _("\
+%s: missing era name in string %Zd in `era' field"), "LC_TIME", idx + 1);
              time->era_entries[idx].name =
                time->era_entries[idx].format = "";
            }
@@ -420,10 +446,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
 
              if (str == NULL || *str == '\0')
                {
-                 if (!be_quiet)
-                   error (0, 0, _("%s: missing era format in string %d"
-                                  " in `era' field"),
-                          "LC_TIME", idx + 1);
+                 record_error (0, 0, _("\
+%s: missing era format in string %Zd in `era' field"),
+                               "LC_TIME", idx + 1);
                  time->era_entries[idx].name =
                    time->era_entries[idx].format = "";
                }
@@ -436,421 +461,215 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end offset */
          wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end start */
          wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end end */
-         time->era_entries[idx].wname = (uint32_t *) wstr + 1;
-         wstr = wstr ? wcschr (wstr + 1, L':') : NULL; /* end name */
-         *wstr = L'\0';
-         time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
+         if (wstr != NULL)
+           {
+             time->era_entries[idx].wname = (uint32_t *) wstr + 1;
+             wstr = wcschr (wstr + 1, L':');   /* end name */
+             if (wstr != NULL)
+               {
+                 *wstr = L'\0';
+                 time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
+               }
+             else
+               time->era_entries[idx].wname =
+                 time->era_entries[idx].wformat = (uint32_t *) L"";
+           }
+         else
+           time->era_entries[idx].wname =
+             time->era_entries[idx].wformat = (uint32_t *) L"";
        }
     }
 
+  /* Set up defaults based on ISO 30112 WD10 [2014].  */
   if (time->week_ndays == 0)
     time->week_ndays = 7;
 
   if (time->week_1stday == 0)
     time->week_1stday = 19971130;
 
+  if (time->week_1stweek == 0)
+    time->week_1stweek = 7;
+
   if (time->week_1stweek > time->week_ndays)
-    error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: third operand for value of field `%s' must not be larger than %d"),
-          "LC_TIME", "week", 7);
+                 "LC_TIME", "week", 7);
 
   if (time->first_weekday == '\0')
     /* The definition does not specify this so the default is used.  */
     time->first_weekday = 1;
   else if (time->first_weekday > time->week_ndays)
-    error (0, 0, _("\
-%s: values of field `%s' must not be larger than %d"),
-          "LC_TIME", "first_weekday", 7);
+    record_error (0, 0, _("\
+%s: values for field `%s' must not be larger than %d"),
+                 "LC_TIME", "first_weekday", 7);
 
   if (time->first_workday == '\0')
     /* The definition does not specify this so the default is used.  */
-    time->first_workday = 1;
+    time->first_workday = 2;
   else if (time->first_workday > time->week_ndays)
-    error (0, 0, _("\
-%s: values of field `%s' must not be larger than %d"),
-          "LC_TIME", "first_workday", 7);
+    record_error (0, 0, _("\
+%s: values for field `%s' must not be larger than %d"),
+                 "LC_TIME", "first_workday", 7);
 
   if (time->cal_direction == '\0')
     /* The definition does not specify this so the default is used.  */
     time->cal_direction = 1;
   else if (time->cal_direction > 3)
-    error (0, 0, _("\
-%s: values for field `%s' must not be larger than 3"),
-          "LC_TIME", "cal_direction", 3);
+    record_error (0, 0, _("\
+%s: values for field `%s' must not be larger than %d"),
+                 "LC_TIME", "cal_direction", 3);
 
   /* XXX We don't perform any tests on the timezone value since this is
      simply useless, stupid $&$!@...  */
   if (time->timezone == NULL)
     time->timezone = "";
+
+  if (time->date_fmt == NULL)
+    time->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
+  if (time->wdate_fmt == NULL)
+    time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y";
 }
 
 
 void
-time_output (struct localedef_t *locale, struct charmap_t *charmap,
+time_output (struct localedef_t *locale, const struct charmap_t *charmap,
             const char *output_path)
 {
   struct locale_time_t *time = locale->categories[LC_TIME].time;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
-                 + time->num_era - 1
-                 + 2 * 99
-                 + 1 + time->num_era * 10 - 1];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
-  size_t cnt, last_idx, num, n;
+  struct locale_file file;
+  size_t num, n;
 
-  data.magic = LIMAGIC (LC_TIME);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TIME);
-  iov[0].iov_base = (void *) &data;
-  iov[0].iov_len = sizeof (data);
-
-  iov[1].iov_base = (void *) idx;
-  iov[1].iov_len = sizeof (idx);
-
-  idx[0] = iov[0].iov_len + iov[1].iov_len;
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
 
   /* The ab'days.  */
-  for (cnt = 0; cnt <= _NL_ITEM_INDEX (ABDAY_7); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->abday[cnt - _NL_ITEM_INDEX (ABDAY_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_string (&file, time->abday[n] ?: "");
 
   /* The days.  */
-  for (; cnt <= _NL_ITEM_INDEX (DAY_7); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->day[cnt - _NL_ITEM_INDEX (DAY_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_string (&file, time->day[n] ?: "");
 
   /* The ab'mons.  */
-  for (; cnt <= _NL_ITEM_INDEX (ABMON_12); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->abmon[cnt - _NL_ITEM_INDEX (ABMON_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->abmon[n] ?: "");
 
   /* The mons.  */
-  for (; cnt <= _NL_ITEM_INDEX (MON_12); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->mon[cnt - _NL_ITEM_INDEX (MON_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->mon[n] ?: "");
 
   /* AM/PM.  */
-  for (; cnt <= _NL_ITEM_INDEX (PM_STR); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->am_pm[cnt - _NL_ITEM_INDEX (AM_STR)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 2; ++n)
+    add_locale_string (&file, time->am_pm[n]);
 
-  iov[2 + cnt].iov_base = (void *) (time->d_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  add_locale_string (&file, time->d_t_fmt ?: "");
+  add_locale_string (&file, time->d_fmt ?: "");
+  add_locale_string (&file, time->t_fmt ?: "");
+  add_locale_string (&file, time->t_fmt_ampm ?: "");
 
-  iov[2 + cnt].iov_base = (void *) (time->d_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  start_locale_structure (&file);
+  for (num = 0; num < time->num_era; ++num)
+    add_locale_string (&file, time->era[num]);
+  end_locale_structure (&file);
 
-  iov[2 + cnt].iov_base = (void *) (time->t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  add_locale_string (&file, time->era_year ?: "");
+  add_locale_string (&file, time->era_d_fmt ?: "");
 
-  iov[2 + cnt].iov_base = (void *) (time->t_fmt_ampm ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  last_idx = ++cnt;
+  start_locale_structure (&file);
+  for (num = 0; num < 100; ++num)
+    add_locale_string (&file, time->alt_digits[num] ?: "");
+  end_locale_structure (&file);
 
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < time->num_era; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) time->era[num];
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_year ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < 100; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) (time->alt_digits[num] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_d_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-
-  /* We must align the following data.  */
-  iov[2 + cnt].iov_base = (void *) "\0\0";
-  iov[2 + cnt].iov_len = ((idx[last_idx] + 3) & ~3) - idx[last_idx];
-  idx[last_idx] = (idx[last_idx] + 3) & ~3;
-  ++cnt;
-
-  /* The `era' data in usable form.  */
-  iov[2 + cnt].iov_base = (void *) &time->num_era;
-  iov[2 + cnt].iov_len = sizeof (uint32_t);
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
+  add_locale_string (&file, time->era_d_t_fmt ?: "");
+  add_locale_string (&file, time->era_t_fmt ?: "");
+  add_locale_uint32 (&file, time->num_era);
+
+  start_locale_structure (&file);
   for (num = 0; num < time->num_era; ++num)
     {
-      size_t l;
-
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].direction;
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].offset;
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[0];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[1];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[2];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[0];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[1];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[2];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-
-      l = (strchr (time->era_entries[num].format, '\0')
-          - time->era_entries[num].name) + 1;
-      l = (l + 3) & ~3;
-      iov[2 + cnt].iov_base = (void *) time->era_entries[num].name;
-      iov[2 + cnt].iov_len = l;
-      ++cnt;
-
-      idx[1 + last_idx] += 8 * sizeof (int32_t) + l;
-
-      assert (idx[1 + last_idx] % 4 == 0);
-
-      iov[2 + cnt].iov_base = (void *) time->era_entries[num].wname;
-      iov[2 + cnt].iov_len = ((wcschr ((wchar_t *) time->era_entries[num].wformat, L'\0')
-                              - (wchar_t *) time->era_entries[num].wname + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-      ++cnt;
+      add_locale_uint32 (&file, time->era_entries[num].direction);
+      add_locale_uint32 (&file, time->era_entries[num].offset);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[0]);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[1]);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[2]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[0]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[1]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[2]);
+      add_locale_string (&file, time->era_entries[num].name);
+      add_locale_string (&file, time->era_entries[num].format);
+      add_locale_wstring (&file, time->era_entries[num].wname);
+      add_locale_wstring (&file, time->era_entries[num].wformat);
     }
-  ++last_idx;
+  end_locale_structure (&file);
 
   /* The wide character ab'days.  */
-  for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->wabday[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_wstring (&file, time->wabday[n] ?: empty_wstr);
 
   /* The wide character days.  */
-  for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->wday[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_wstring (&file, time->wday[n] ?: empty_wstr);
 
   /* The wide character ab'mons.  */
-  for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->wabmon[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->wabmon[n] ?: empty_wstr);
 
   /* The wide character mons.  */
-  for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->wmon[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->wmon[n] ?: empty_wstr);
 
   /* Wide character AM/PM.  */
-  for (n = 0; n < 2; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-       (void *) (time->wam_pm[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
-
-  iov[2 + cnt].iov_base = (void *) (time->wd_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wd_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wt_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wt_fmt_ampm ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_year ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_d_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < 100; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) (time->walt_digits[num]
-                                       ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                             * sizeof (uint32_t));
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_d_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                         * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_ndays;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_1stday;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_1stweek;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->first_weekday;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->first_workday;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->cal_direction;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) time->timezone;
-  iov[2 + cnt].iov_len = strlen (time->timezone) + 1;
-  ++cnt;
-  ++last_idx;
-
-  assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME)
-                 + time->num_era - 1
-                 + 2 * 99
-                 + 1 + time->num_era * 10 - 1));
-  assert (last_idx  == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
-
-  write_locale_data (output_path, "LC_TIME", 2 + cnt, iov);
+  for (n = 0; n < 2; ++n)
+    add_locale_wstring (&file, time->wam_pm[n] ?: empty_wstr);
+
+  add_locale_wstring (&file, time->wd_t_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wd_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wt_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wt_fmt_ampm ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_year ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_d_fmt ?: empty_wstr);
+
+  start_locale_structure (&file);
+  for (num = 0; num < 100; ++num)
+    add_locale_wstring (&file, time->walt_digits[num] ?: empty_wstr);
+  end_locale_structure (&file);
+
+  add_locale_wstring (&file, time->wera_d_t_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_t_fmt ?: empty_wstr);
+  add_locale_char (&file, time->week_ndays);
+  add_locale_uint32 (&file, time->week_1stday);
+  add_locale_char (&file, time->week_1stweek);
+  add_locale_char (&file, time->first_weekday);
+  add_locale_char (&file, time->first_workday);
+  add_locale_char (&file, time->cal_direction);
+  add_locale_string (&file, time->timezone);
+  add_locale_string (&file, time->date_fmt);
+  add_locale_wstring (&file, time->wdate_fmt);
+  add_locale_string (&file, charmap->code_set_name);
+
+  /* The alt'mons.  */
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->alt_mon[n] ?: "");
+
+  /* The wide character alt'mons.  */
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->walt_mon[n] ?: empty_wstr);
+
+  /* The ab'alt'mons.  */
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->ab_alt_mon[n] ?: "");
+
+  /* The wide character ab'alt'mons.  */
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->wab_alt_mon[n] ?: empty_wstr);
+
+  write_locale_data (output_path, LC_TIME, "LC_TIME", &file);
 }
 
 
 /* The parser for the LC_TIME section of the locale definition.  */
 void
 time_read (struct linereader *ldfile, struct localedef_t *result,
-          struct charmap_t *charmap, const char *repertoire_name,
+          const struct charmap_t *charmap, const char *repertoire_name,
           int ignore_content)
 {
   struct repertoire_t *repertoire = NULL;
@@ -869,7 +688,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
 
   do
     {
-      now = lr_token (ldfile, charmap, repertoire);
+      now = lr_token (ldfile, charmap, result, repertoire, verbose);
       nowtok = now->tok;
     }
   while (nowtok == tok_eol);
@@ -877,7 +696,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
   /* If we see `copy' now we are almost done.  */
   if (nowtok == tok_copy)
     {
-      handle_copy (ldfile, charmap, repertoire, result, tok_lc_time,
+      handle_copy (ldfile, charmap, repertoire_name, result, tok_lc_time,
                   LC_TIME, "LC_TIME", ignore_content);
       return;
     }
@@ -895,7 +714,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
       /* Ingore empty lines.  */
       if (nowtok == tok_eol)
        {
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          nowtok = now->tok;
          continue;
        }
@@ -914,7 +733,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                                                                              \
          for (cnt = 0; cnt < max; ++cnt)                                     \
            {                                                                 \
-             now = lr_token (ldfile, charmap, repertoire);                   \
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);  \
              if (now->tok == tok_eol)                                        \
                {                                                             \
                  if (cnt < min)                                              \
@@ -946,7 +765,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                }                                                             \
                                                                              \
              /* Match the semicolon.  */                                     \
-             now = lr_token (ldfile, charmap, repertoire);                   \
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);  \
              if (now->tok != tok_semicolon && now->tok != tok_eol)           \
                break;                                                        \
            }                                                                 \
@@ -957,10 +776,11 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                  time->cat[cnt] = "";                                        \
                  time->w##cat[cnt++] = empty_wstr;                           \
                }                                                             \
-                                                                             \
+                                                                             \
              if (now->tok == tok_semicolon)                                  \
                {                                                             \
-                 now = lr_token (ldfile, charmap, repertoire);               \
+                 now = lr_token (ldfile, charmap, result, repertoire,        \
+                                 verbose);                                   \
                  if (now->tok == tok_eol)                                    \
                    lr_error (ldfile, _("extra trailing semicolon"));         \
                  else if (now->tok == tok_string)                            \
@@ -985,6 +805,8 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
          STRARR_ELEM (mon, 12, 12);
          STRARR_ELEM (am_pm, 2, 2);
          STRARR_ELEM (alt_digits, 0, 100);
+         STRARR_ELEM (alt_mon, 12, 12);
+         STRARR_ELEM (ab_alt_mon, 12, 12);
 
        case tok_era:
          /* Ignore the rest of the line if we don't need the input of
@@ -996,7 +818,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
            }
          do
            {
-             now = lr_token (ldfile, charmap, repertoire);
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);
              if (now->tok != tok_string)
                goto err_label;
              if (!ignore_content && (now->val.str.startmb == NULL
@@ -1018,7 +840,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                                         * sizeof (char *));
                  time->wera[time->num_era++] = now->val.str.startwc;
                }
-             now = lr_token (ldfile, charmap, repertoire);
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);
              if (now->tok != tok_eol && now->tok != tok_semicolon)
                goto err_label;
            }
@@ -1035,7 +857,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;                                                          \
            }                                                                 \
                                                                              \
-         now = lr_token (ldfile, charmap, repertoire);                       \
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);      \
          if (now->tok != tok_string)                                         \
            goto err_label;                                                   \
          else if (time->cat != NULL)                                         \
@@ -1065,6 +887,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
          STR_ELEM (era_d_fmt);
          STR_ELEM (era_t_fmt);
          STR_ELEM (timezone);
+         STR_ELEM (date_fmt);
 
 #define INT_ELEM(cat) \
        case tok_##cat:                                                       \
@@ -1076,7 +899,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;                                                          \
            }                                                                 \
                                                                              \
-         now = lr_token (ldfile, charmap, repertoire);                       \
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);      \
          if (now->tok != tok_number)                                         \
            goto err_label;                                                   \
          else if (time->cat != 0)                                            \
@@ -1099,25 +922,25 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;
            }
 
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_number)
            goto err_label;
          time->week_ndays = now->val.num;
 
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_semicolon)
            goto err_label;
 
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_number)
            goto err_label;
          time->week_1stday = now->val.num;
 
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_semicolon)
            goto err_label;
 
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_number)
            goto err_label;
          time->week_1stweek = now->val.num;
@@ -1127,7 +950,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
 
        case tok_end:
          /* Next we assume `LC_TIME'.  */
-         now = lr_token (ldfile, charmap, repertoire);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok == tok_eof)
            break;
          if (now->tok == tok_eol)
@@ -1136,6 +959,21 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
            lr_error (ldfile, _("\
 %1$s: definition does not end with `END %1$s'"), "LC_TIME");
          lr_ignore_rest (ldfile, now->tok == tok_lc_time);
+
+         /* If alt_mon was not specified, make it a copy of mon.  */
+         if (!ignore_content && !time->alt_mon_defined)
+           {
+             memcpy (time->alt_mon, time->mon, sizeof (time->mon));
+             memcpy (time->walt_mon, time->wmon, sizeof (time->wmon));
+             time->alt_mon_defined = 1;
+           }
+         /* The same for abbreviated versions.  */
+         if (!ignore_content && !time->ab_alt_mon_defined)
+           {
+             memcpy (time->ab_alt_mon, time->abmon, sizeof (time->abmon));
+             memcpy (time->wab_alt_mon, time->wabmon, sizeof (time->wabmon));
+             time->ab_alt_mon_defined = 1;
+           }
          return;
 
        default:
@@ -1144,7 +982,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
        }
 
       /* Prepare for the next round.  */
-      now = lr_token (ldfile, charmap, repertoire);
+      now = lr_token (ldfile, charmap, result, repertoire, verbose);
       nowtok = now->tok;
     }