summary refs log tree commit diff
path: root/locale/lc-time.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/lc-time.c')
-rw-r--r--locale/lc-time.c156
1 files changed, 155 insertions, 1 deletions
diff --git a/locale/lc-time.c b/locale/lc-time.c
index 7b84f99dc2..f4fe561cb9 100644
--- a/locale/lc-time.c
+++ b/locale/lc-time.c
@@ -1,5 +1,5 @@
 /* Define current locale data for LC_TIME category.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -17,6 +17,160 @@ License along with the GNU C Library; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
+#include <libc-lock.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
 #include "localeinfo.h"
 
 _NL_CURRENT_DEFINE (LC_TIME);
+
+/* Some of the functions here must not be used while setlocale is called.  */
+__libc_lock_define (extern, __libc_setlocale_lock)
+
+
+static int era_initialized;
+static struct era_entry **eras;
+static size_t num_eras;
+
+
+static int alt_digits_initialized;
+static const char **alt_digits;
+static size_t num_alt_digits;
+
+
+void
+_nl_postload_time (void)
+{
+  /* Prepare lazy initialization of `era' and `alt_digits' array.  */
+  era_initialized = 0;
+  alt_digits_initialized = 0;
+}
+
+
+struct era_entry *
+_nl_get_era_entry (const struct tm *tp)
+{
+  struct era_entry *result;
+  size_t cnt;
+
+  __libc_lock_lock (__libc_setlocale_lock);
+
+  if (era_initialized == 0)
+    {
+      size_t new_num_eras = _NL_CURRENT_WORD (LC_TIME,
+					      _NL_TIME_ERA_NUM_ENTRIES);
+
+      if (eras != NULL && new_num_eras == 0)
+	{
+	  free (eras);
+	  eras = NULL;
+	}
+      else if (new_num_eras != 0)
+	{
+	  if (num_eras != new_num_eras)
+	    eras = realloc (eras, new_num_eras * sizeof (struct era_entry *));
+
+	  if (eras == NULL)
+	    num_eras = 0;
+	  else
+	    {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	      const char *ptr = _NL_CURRENT (LC_TIME, _NL_TIME_ERA_ENTRIES_EL);
+#else
+	      const char *ptr = _NL_CURRENT (LC_TIME, _NL_TIME_ERA_ENTRIES_EB);
+#endif
+	      num_eras = new_num_eras;
+
+	      for (cnt = 0; cnt < num_eras; ++cnt)
+		{
+		  eras[cnt] = (struct era_entry *) ptr;
+
+		  /* Skip numeric values.  */
+		  ptr += sizeof (struct era_entry);
+		  /* Skip era name. */
+		  ptr = strchr (ptr, '\0') + 1;
+		  /* Skip era format. */
+		  ptr = strchr (ptr, '\0') + 1;
+
+		  ptr += 3 - (((ptr - (const char *) eras[cnt]) + 3) & 3);
+		}
+	    }
+	}
+
+      era_initialized = 1;
+    }
+
+  /* Now compare date with the available eras.  */
+  for (cnt = 0; cnt < num_eras; ++cnt)
+    if ((eras[cnt]->start_date[0] < tp->tm_year
+	 || (eras[cnt]->start_date[0] == tp->tm_year
+	     && (eras[cnt]->start_date[1] < tp->tm_mon
+		 || (eras[cnt]->start_date[1] == tp->tm_mon
+		     && eras[cnt]->start_date[2] <= tp->tm_mday))))
+	&& (eras[cnt]->stop_date[0] > tp->tm_year
+	    || (eras[cnt]->stop_date[0] == tp->tm_year
+		&& (eras[cnt]->stop_date[1] > tp->tm_mon
+		    || (eras[cnt]->stop_date[1] == tp->tm_mon
+			&& eras[cnt]->stop_date[2] >= tp->tm_mday)))))
+      break;
+
+  result = cnt < num_eras ? eras[cnt] : NULL;
+
+  __libc_lock_unlock (__libc_setlocale_lock);
+
+  return result;
+}
+
+
+const char *
+_nl_get_alt_digit (unsigned int number)
+{
+  const char *result;
+
+  __libc_lock_lock (__libc_setlocale_lock);
+
+  if (alt_digits_initialized == 0)
+    {
+      size_t new_num_alt_digits = _NL_CURRENT_WORD (LC_TIME,
+						    _NL_TIME_NUM_ALT_DIGITS);
+
+      if (alt_digits != NULL && new_num_alt_digits == 0)
+	{
+	  free (alt_digits);
+	  alt_digits = NULL;
+	}
+      else if (new_num_alt_digits != 0)
+	{
+	  if (num_alt_digits != new_num_alt_digits)
+	    alt_digits = realloc (alt_digits, (new_num_alt_digits
+					       * sizeof (const char *)));
+
+	  if (alt_digits == NULL)
+	    num_alt_digits = 0;
+	  else
+	    {
+	      const char *ptr = _NL_CURRENT (LC_TIME, ALT_DIGITS);
+	      size_t cnt;
+
+	      num_alt_digits = new_num_alt_digits;
+
+	      for (cnt = 0; cnt < num_alt_digits; ++cnt)
+		{
+		  alt_digits[cnt] = ptr;
+
+		  /* Skip digit format. */
+		  ptr = strchr (ptr, '\0') + 1;
+		}
+	    }
+	}
+
+      alt_digits_initialized = 1;
+    }
+
+  result = number < num_alt_digits ? alt_digits[number] : NULL;
+
+  __libc_lock_unlock (__libc_setlocale_lock);
+
+  return result;
+}