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
20 #include <bits/libc-lock.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
;
47 _nl_postload_time (void)
49 /* Prepare lazy initialization of `era' and `alt_digits' array. */
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]))))
60 _nl_init_era_entries (void)
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)
77 if (num_eras
!= new_num_eras
)
78 eras
= (struct era_entry
*) realloc (eras
,
80 * sizeof (struct era_entry
));
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
,
99 if (eras
[cnt
].direction
== (uint32_t) '+')
100 eras
[cnt
].absolute_direction
= 1;
102 eras
[cnt
].absolute_direction
= -1;
104 if (eras
[cnt
].direction
== (uint32_t) '+')
105 eras
[cnt
].absolute_direction
= -1;
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);
136 __libc_lock_unlock (__libc_setlocale_lock
);
141 _nl_get_era_entry (const struct tm
*tp
)
143 struct era_entry
*result
;
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
)))
162 result
= cnt
< num_eras
? &eras
[cnt
] : NULL
;
169 _nl_select_era_entry (int cnt
)
171 if (era_initialized
== 0)
172 _nl_init_era_entries ();
179 _nl_get_alt_digit (unsigned int number
)
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
);
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
);
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
);
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
;
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
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)
301 __libc_lock_unlock (__libc_setlocale_lock
);
316 text_set_element (__libc_subfreeres
, free_mem
);