* catgets/gencat.c: Use GPL, not LGPL.
[platform/upstream/glibc.git] / locale / programs / ld-time.c
index e60becc..2d63275 100644 (file)
@@ -1,21 +1,19 @@
-/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2002, 2003, 2004, 2005 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 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 free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation.
 
-   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
-   Lesser 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 Lesser General Public
-   License along with the GNU C Library; 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, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -30,8 +28,8 @@
 
 #include <assert.h>
 
-#include "linereader.h"
 #include "localedef.h"
+#include "linereader.h"
 #include "localeinfo.h"
 #include "locfile.h"
 
@@ -126,7 +124,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;
@@ -157,44 +155,68 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
       if (time == NULL)
        {
          if (! be_quiet)
-           error (0, 0, _("No definition for %s category found"), "LC_TIME");
+           WITH_CUR_LOCALE (error (0, 0, _("\
+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 (! be_quiet && ! nothing)                                           \
+       WITH_CUR_LOCALE (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);       \
+       WITH_CUR_LOCALE (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.  */
@@ -221,10 +243,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          if (*str != '+' && *str != '-')
            {
              if (!be_quiet)
-               error (0, 0,
-                      _("%s: direction flag in string %Zd in `era' field"
-                        " is not '+' nor '-'"),
-                      "LC_TIME", idx + 1);
+               WITH_CUR_LOCALE (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 = '+';
            }
@@ -233,10 +254,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          if (*++str != ':')
            {
              if (!be_quiet)
-               error (0, 0,
-                      _("%s: direction flag in string %Zd in `era' field"
-                        " is not a single character"),
-                      "LC_TIME", idx + 1);
+               WITH_CUR_LOCALE (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
@@ -247,17 +267,17 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
          if (endp == str)
            {
              if (!be_quiet)
-               error (0, 0, _("%s: invalid number for offset in string %Zd in"
-                              " `era' field"),
-                      "LC_TIME", idx + 1);
+               WITH_CUR_LOCALE (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 %Zd in `era' field"),
-                      "LC_TIME", idx + 1);
+               WITH_CUR_LOCALE (error (0, 0, _("\
+%s: garbage at end of offset value in string %Zd in `era' field"),
+                                       "LC_TIME", idx + 1));
              (void) strsep (&str, ":");
            }
          else
@@ -306,18 +326,18 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                {
                invalid_start_date:
                  if (!be_quiet)
-                   error (0, 0, _("%s: invalid starting date in string %Zd in"
-                                  " `era' field"),
-                          "LC_TIME", idx + 1);
+                   WITH_CUR_LOCALE (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 %Zd in `era' field "),
-                          "LC_TIME", idx + 1);
+                   WITH_CUR_LOCALE (error (0, 0, _("\
+%s: garbage at end of starting date in string %Zd in `era' field "),
+                                           "LC_TIME", idx + 1));
                  (void) strsep (&str, ":");
                }
              else
@@ -334,9 +354,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                           && 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 %Zd in `era' field"),
-                                "LC_TIME", idx + 1);
+                         WITH_CUR_LOCALE (error (0, 0, _("\
+%s: starting date is invalid in string %Zd in `era' field"),
+                                                 "LC_TIME", idx + 1));
                }
            }
 
@@ -383,18 +403,18 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                {
                invalid_stop_date:
                  if (!be_quiet)
-                   error (0, 0, _("%s: invalid stopping date in string %Zd in"
-                                  " `era' field"),
-                          "LC_TIME", idx + 1);
+                   WITH_CUR_LOCALE (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 %Zd in `era' field"),
-                          "LC_TIME", idx + 1);
+                   WITH_CUR_LOCALE (error (0, 0, _("\
+%s: garbage at end of stopping date in string %Zd in `era' field"),
+                                           "LC_TIME", idx + 1));
                  (void) strsep (&str, ":");
                }
              else
@@ -411,17 +431,17 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
                           && 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 %Zd in `era' field"),
-                                "LC_TIME", idx + 1);
+                         WITH_CUR_LOCALE (error (0, 0, _("\
+%s: stopping date is invalid 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 %Zd in `era'"
-                              " field"), "LC_TIME", idx + 1);
+               WITH_CUR_LOCALE (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 = "";
            }
@@ -432,9 +452,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 %Zd"
-                                  " in `era' field"),
-                          "LC_TIME", idx + 1);
+                   WITH_CUR_LOCALE (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 = "";
                }
@@ -461,33 +481,33 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
     time->week_1stday = 19971130;
 
   if (time->week_1stweek > time->week_ndays)
-    error (0, 0, _("\
+    WITH_CUR_LOCALE (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, _("\
+    WITH_CUR_LOCALE (error (0, 0, _("\
 %s: values of field `%s' must not be larger than %d"),
-          "LC_TIME", "first_weekday", 7);
+                           "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;
   else if (time->first_workday > time->week_ndays)
-    error (0, 0, _("\
+    WITH_CUR_LOCALE (error (0, 0, _("\
 %s: values of field `%s' must not be larger than %d"),
-          "LC_TIME", "first_workday", 7);
+                           "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, _("\
+    WITH_CUR_LOCALE (error (0, 0, _("\
 %s: values for field `%s' must not be larger than %d"),
-          "LC_TIME", "cal_direction", 3);
+                           "LC_TIME", "cal_direction", 3));
 
   /* XXX We don't perform any tests on the timezone value since this is
      simply useless, stupid $&$!@...  */
@@ -502,14 +522,15 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap)
 
 
 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
-                 + 2 + time->num_era * 10 - 1];
+  struct iovec *iov = alloca (sizeof *iov
+                             * (2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
+                                + time->num_era - 1
+                                + 2 * 99
+                                + 2 + 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;
@@ -648,7 +669,7 @@ time_output (struct localedef_t *locale, struct charmap_t *charmap,
   idx[1 + last_idx] = idx[last_idx];
   for (num = 0; num < time->num_era; ++num)
     {
-      size_t l;
+      size_t l, l2;
 
       iov[2 + cnt].iov_base = (void *) &time->era_entries[num].direction;
       iov[2 + cnt].iov_len = sizeof (int32_t);
@@ -675,14 +696,16 @@ time_output (struct localedef_t *locale, struct charmap_t *charmap,
       iov[2 + cnt].iov_len = sizeof (int32_t);
       ++cnt;
 
-      l = (strchr (time->era_entries[num].format, '\0')
+      l = ((char *) rawmemchr (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;
+      l2 = (l + 3) & ~3;
+      iov[2 + cnt].iov_base = alloca (l2);
+      memset (mempcpy (iov[2 + cnt].iov_base, time->era_entries[num].name, l),
+             '\0', l2 - l);
+      iov[2 + cnt].iov_len = l2;
       ++cnt;
 
-      idx[1 + last_idx] += 8 * sizeof (int32_t) + l;
+      idx[1 + last_idx] += 8 * sizeof (int32_t) + l2;
 
       assert (idx[1 + last_idx] % 4 == 0);
 
@@ -884,14 +907,14 @@ time_output (struct localedef_t *locale, struct charmap_t *charmap,
                  + 2 + 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);
+  write_locale_data (output_path, LC_TIME, "LC_TIME", 2 + cnt, iov);
 }
 
 
 /* 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;
@@ -910,7 +933,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
 
   do
     {
-      now = lr_token (ldfile, charmap, repertoire, verbose);
+      now = lr_token (ldfile, charmap, result, repertoire, verbose);
       nowtok = now->tok;
     }
   while (nowtok == tok_eol);
@@ -936,7 +959,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
       /* Ingore empty lines.  */
       if (nowtok == tok_eol)
        {
-         now = lr_token (ldfile, charmap, repertoire, verbose);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          nowtok = now->tok;
          continue;
        }
@@ -955,7 +978,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                                                                              \
          for (cnt = 0; cnt < max; ++cnt)                                     \
            {                                                                 \
-             now = lr_token (ldfile, charmap, repertoire, verbose);          \
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);  \
              if (now->tok == tok_eol)                                        \
                {                                                             \
                  if (cnt < min)                                              \
@@ -987,7 +1010,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                }                                                             \
                                                                              \
              /* Match the semicolon.  */                                     \
-             now = lr_token (ldfile, charmap, repertoire, verbose);          \
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);  \
              if (now->tok != tok_semicolon && now->tok != tok_eol)           \
                break;                                                        \
            }                                                                 \
@@ -1001,7 +1024,8 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
                                                                              \
              if (now->tok == tok_semicolon)                                  \
                {                                                             \
-                 now = lr_token (ldfile, charmap, repertoire, verbose);      \
+                 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)                            \
@@ -1037,7 +1061,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
            }
          do
            {
-             now = lr_token (ldfile, charmap, repertoire, verbose);
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);
              if (now->tok != tok_string)
                goto err_label;
              if (!ignore_content && (now->val.str.startmb == NULL
@@ -1059,7 +1083,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, verbose);
+             now = lr_token (ldfile, charmap, result, repertoire, verbose);
              if (now->tok != tok_eol && now->tok != tok_semicolon)
                goto err_label;
            }
@@ -1076,7 +1100,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;                                                          \
            }                                                                 \
                                                                              \
-         now = lr_token (ldfile, charmap, repertoire, verbose);              \
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);      \
          if (now->tok != tok_string)                                         \
            goto err_label;                                                   \
          else if (time->cat != NULL)                                         \
@@ -1118,7 +1142,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;                                                          \
            }                                                                 \
                                                                              \
-         now = lr_token (ldfile, charmap, repertoire, verbose);              \
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);      \
          if (now->tok != tok_number)                                         \
            goto err_label;                                                   \
          else if (time->cat != 0)                                            \
@@ -1141,25 +1165,25 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
              break;
            }
 
-         now = lr_token (ldfile, charmap, repertoire, verbose);
+         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, verbose);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_semicolon)
            goto err_label;
 
-         now = lr_token (ldfile, charmap, repertoire, verbose);
+         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, verbose);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_semicolon)
            goto err_label;
 
-         now = lr_token (ldfile, charmap, repertoire, verbose);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok != tok_number)
            goto err_label;
          time->week_1stweek = now->val.num;
@@ -1169,7 +1193,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
 
        case tok_end:
          /* Next we assume `LC_TIME'.  */
-         now = lr_token (ldfile, charmap, repertoire, verbose);
+         now = lr_token (ldfile, charmap, result, repertoire, verbose);
          if (now->tok == tok_eof)
            break;
          if (now->tok == tok_eol)
@@ -1186,7 +1210,7 @@ time_read (struct linereader *ldfile, struct localedef_t *result,
        }
 
       /* Prepare for the next round.  */
-      now = lr_token (ldfile, charmap, repertoire, verbose);
+      now = lr_token (ldfile, charmap, result, repertoire, verbose);
       nowtok = now->tok;
     }