summaryrefslogtreecommitdiff
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;
+}