(pthread_handle_create): Start the child thread with the cancel signal blocked, so...
[glibc.git] / locale / lc-time.c
blobefa56b8f828f9dcf4c2054085c2b6763237bf013
1 /* Define current locale data for LC_TIME category.
2 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <bits/libc-lock.h>
21 #include <endian.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <wchar.h>
26 #include "localeinfo.h"
28 _NL_CURRENT_DEFINE (LC_TIME);
30 /* Some of the functions here must not be used while setlocale is called. */
31 __libc_lock_define (extern, __libc_setlocale_lock)
34 static int era_initialized;
36 static struct era_entry *eras;
37 static size_t num_eras;
38 static int alt_digits_initialized;
39 static const char **alt_digits;
42 static int walt_digits_initialized;
43 static const wchar_t **walt_digits;
46 void
47 _nl_postload_time (void)
49 /* Prepare lazy initialization of `era' and `alt_digits' array. */
50 era_initialized = 0;
51 alt_digits_initialized = 0;
52 walt_digits_initialized = 0;
55 #define ERA_DATE_CMP(a, b) \
56 (a[0] < b[0] || (a[0] == b[0] && (a[1] < b[1] \
57 || (a[1] == b[1] && a[2] <= b[2]))))
59 static void
60 _nl_init_era_entries (void)
62 size_t cnt;
64 __libc_lock_lock (__libc_setlocale_lock);
66 if (era_initialized == 0)
68 size_t new_num_eras = _NL_CURRENT_WORD (LC_TIME,
69 _NL_TIME_ERA_NUM_ENTRIES);
70 if (new_num_eras == 0)
72 free (eras);
73 eras = NULL;
75 else
77 if (num_eras != new_num_eras)
78 eras = (struct era_entry *) realloc (eras,
79 new_num_eras
80 * sizeof (struct era_entry));
81 if (eras == NULL)
83 num_eras = 0;
84 eras = NULL;
86 else
88 const char *ptr = _NL_CURRENT (LC_TIME, _NL_TIME_ERA_ENTRIES);
89 num_eras = new_num_eras;
91 for (cnt = 0; cnt < num_eras; ++cnt)
93 const char *base_ptr = ptr;
94 memcpy ((void *) (eras + cnt), (const void *) ptr,
95 sizeof (uint32_t) * 8);
97 if (ERA_DATE_CMP(eras[cnt].start_date,
98 eras[cnt].stop_date))
99 if (eras[cnt].direction == (uint32_t) '+')
100 eras[cnt].absolute_direction = 1;
101 else
102 eras[cnt].absolute_direction = -1;
103 else
104 if (eras[cnt].direction == (uint32_t) '+')
105 eras[cnt].absolute_direction = -1;
106 else
107 eras[cnt].absolute_direction = 1;
109 /* Skip numeric values. */
110 ptr += sizeof (uint32_t) * 8;
112 /* Set and skip era name. */
113 eras[cnt].era_name = ptr;
114 ptr = strchr (ptr, '\0') + 1;
116 /* Set and skip era format. */
117 eras[cnt].era_format = ptr;
118 ptr = strchr (ptr, '\0') + 1;
120 ptr += 3 - (((ptr - (const char *) base_ptr) + 3) & 3);
122 /* Set and skip wide era name. */
123 eras[cnt].era_wname = (wchar_t *) ptr;
124 ptr = (char *) (wcschr ((wchar_t *) ptr, L'\0') + 1);
126 /* Set and skip wide era format. */
127 eras[cnt].era_wformat = (wchar_t *) ptr;
128 ptr = (char *) (wcschr ((wchar_t *) ptr, L'\0') + 1);
133 era_initialized = 1;
136 __libc_lock_unlock (__libc_setlocale_lock);
140 struct era_entry *
141 _nl_get_era_entry (const struct tm *tp)
143 struct era_entry *result;
144 int32_t tdate[3];
145 size_t cnt;
147 tdate[0] = tp->tm_year;
148 tdate[1] = tp->tm_mon;
149 tdate[2] = tp->tm_mday;
151 if (era_initialized == 0)
152 _nl_init_era_entries ();
154 /* Now compare date with the available eras. */
155 for (cnt = 0; cnt < num_eras; ++cnt)
156 if ((ERA_DATE_CMP(eras[cnt].start_date, tdate)
157 && ERA_DATE_CMP(tdate, eras[cnt].stop_date))
158 || (ERA_DATE_CMP(eras[cnt].stop_date, tdate)
159 && ERA_DATE_CMP(tdate, eras[cnt].start_date)))
160 break;
162 result = cnt < num_eras ? &eras[cnt] : NULL;
164 return result;
168 struct era_entry *
169 _nl_select_era_entry (int cnt)
171 if (era_initialized == 0)
172 _nl_init_era_entries ();
174 return &eras[cnt];
178 const char *
179 _nl_get_alt_digit (unsigned int number)
181 const char *result;
183 __libc_lock_lock (__libc_setlocale_lock);
185 if (alt_digits_initialized == 0)
187 alt_digits_initialized = 1;
189 if (alt_digits == NULL)
190 alt_digits = malloc (100 * sizeof (const char *));
192 if (alt_digits != NULL)
194 const char *ptr = _NL_CURRENT (LC_TIME, ALT_DIGITS);
195 size_t cnt;
197 if (alt_digits != NULL)
198 for (cnt = 0; cnt < 100; ++cnt)
200 alt_digits[cnt] = ptr;
202 /* Skip digit format. */
203 ptr = strchr (ptr, '\0') + 1;
208 result = alt_digits != NULL && number < 100 ? alt_digits[number] : NULL;
210 __libc_lock_unlock (__libc_setlocale_lock);
212 return result;
216 const wchar_t *
217 _nl_get_walt_digit (unsigned int number)
219 const wchar_t *result;
221 __libc_lock_lock (__libc_setlocale_lock);
223 if (walt_digits_initialized == 0)
225 walt_digits_initialized = 1;
227 if (walt_digits == NULL)
228 walt_digits = malloc (100 * sizeof (const uint32_t *));
230 if (walt_digits != NULL)
232 const wchar_t *ptr = _NL_CURRENT_WSTR (LC_TIME, _NL_WALT_DIGITS);
233 size_t cnt;
235 for (cnt = 0; cnt < 100; ++cnt)
237 walt_digits[cnt] = ptr;
239 /* Skip digit format. */
240 ptr = wcschr (ptr, L'\0') + 1;
245 result = walt_digits != NULL && number < 100 ? walt_digits[number] : NULL;
247 __libc_lock_unlock (__libc_setlocale_lock);
249 return (wchar_t *) result;
254 _nl_parse_alt_digit (const char **strp)
256 const char *str = *strp;
257 int result = -1;
258 size_t cnt;
259 size_t maxlen = 0;
261 __libc_lock_lock (__libc_setlocale_lock);
263 if (alt_digits_initialized == 0)
265 alt_digits_initialized = 1;
267 if (alt_digits == NULL)
268 alt_digits = malloc (100 * sizeof (const char *));
270 if (alt_digits != NULL)
272 const char *ptr = _NL_CURRENT (LC_TIME, ALT_DIGITS);
274 if (alt_digits != NULL)
275 for (cnt = 0; cnt < 100; ++cnt)
277 alt_digits[cnt] = ptr;
279 /* Skip digit format. */
280 ptr = strchr (ptr, '\0') + 1;
285 /* Matching is not unambiguos. The alternative digits could be like
286 I, II, III, ... and the first one is a substring of the second
287 and third. Therefore we must keep on searching until we found
288 the longest possible match. Note that this is not specified in
289 the standard. */
290 for (cnt = 0; cnt < 100; ++cnt)
292 size_t len = strlen (alt_digits[cnt]);
294 if (len > maxlen && strncmp (alt_digits[cnt], str, len) == 0)
296 maxlen = len;
297 result = (int) cnt;
301 __libc_lock_unlock (__libc_setlocale_lock);
303 if (result != -1)
304 *strp += maxlen;
306 return result;
310 static void
311 free_mem (void)
313 free (alt_digits);
314 free (walt_digits);
316 text_set_element (__libc_subfreeres, free_mem);