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 struct era_entry
*new_eras
= eras
;
79 if (num_eras
!= new_num_eras
)
81 (struct era_entry
*) realloc (eras
,
83 * sizeof (struct era_entry
));
92 const char *ptr
= _NL_CURRENT (LC_TIME
, _NL_TIME_ERA_ENTRIES
);
93 num_eras
= new_num_eras
;
96 for (cnt
= 0; cnt
< num_eras
; ++cnt
)
98 const char *base_ptr
= ptr
;
99 memcpy ((void *) (eras
+ cnt
), (const void *) ptr
,
100 sizeof (uint32_t) * 8);
102 if (ERA_DATE_CMP(eras
[cnt
].start_date
,
103 eras
[cnt
].stop_date
))
104 if (eras
[cnt
].direction
== (uint32_t) '+')
105 eras
[cnt
].absolute_direction
= 1;
107 eras
[cnt
].absolute_direction
= -1;
109 if (eras
[cnt
].direction
== (uint32_t) '+')
110 eras
[cnt
].absolute_direction
= -1;
112 eras
[cnt
].absolute_direction
= 1;
114 /* Skip numeric values. */
115 ptr
+= sizeof (uint32_t) * 8;
117 /* Set and skip era name. */
118 eras
[cnt
].era_name
= ptr
;
119 ptr
= strchr (ptr
, '\0') + 1;
121 /* Set and skip era format. */
122 eras
[cnt
].era_format
= ptr
;
123 ptr
= strchr (ptr
, '\0') + 1;
125 ptr
+= 3 - (((ptr
- (const char *) base_ptr
) + 3) & 3);
127 /* Set and skip wide era name. */
128 eras
[cnt
].era_wname
= (wchar_t *) ptr
;
129 ptr
= (char *) (wcschr ((wchar_t *) ptr
, L
'\0') + 1);
131 /* Set and skip wide era format. */
132 eras
[cnt
].era_wformat
= (wchar_t *) ptr
;
133 ptr
= (char *) (wcschr ((wchar_t *) ptr
, L
'\0') + 1);
141 __libc_lock_unlock (__libc_setlocale_lock
);
146 _nl_get_era_entry (const struct tm
*tp
)
148 struct era_entry
*result
;
152 tdate
[0] = tp
->tm_year
;
153 tdate
[1] = tp
->tm_mon
;
154 tdate
[2] = tp
->tm_mday
;
156 if (era_initialized
== 0)
157 _nl_init_era_entries ();
159 /* Now compare date with the available eras. */
160 for (cnt
= 0; cnt
< num_eras
; ++cnt
)
161 if ((ERA_DATE_CMP(eras
[cnt
].start_date
, tdate
)
162 && ERA_DATE_CMP(tdate
, eras
[cnt
].stop_date
))
163 || (ERA_DATE_CMP(eras
[cnt
].stop_date
, tdate
)
164 && ERA_DATE_CMP(tdate
, eras
[cnt
].start_date
)))
167 result
= cnt
< num_eras
? &eras
[cnt
] : NULL
;
174 _nl_select_era_entry (int cnt
)
176 if (era_initialized
== 0)
177 _nl_init_era_entries ();
184 _nl_get_alt_digit (unsigned int number
)
188 __libc_lock_lock (__libc_setlocale_lock
);
190 if (alt_digits_initialized
== 0)
192 alt_digits_initialized
= 1;
194 if (alt_digits
== NULL
)
195 alt_digits
= malloc (100 * sizeof (const char *));
197 if (alt_digits
!= NULL
)
199 const char *ptr
= _NL_CURRENT (LC_TIME
, ALT_DIGITS
);
202 if (alt_digits
!= NULL
)
203 for (cnt
= 0; cnt
< 100; ++cnt
)
205 alt_digits
[cnt
] = ptr
;
207 /* Skip digit format. */
208 ptr
= strchr (ptr
, '\0') + 1;
213 result
= alt_digits
!= NULL
&& number
< 100 ? alt_digits
[number
] : NULL
;
215 __libc_lock_unlock (__libc_setlocale_lock
);
222 _nl_get_walt_digit (unsigned int number
)
224 const wchar_t *result
;
226 __libc_lock_lock (__libc_setlocale_lock
);
228 if (walt_digits_initialized
== 0)
230 walt_digits_initialized
= 1;
232 if (walt_digits
== NULL
)
233 walt_digits
= malloc (100 * sizeof (const uint32_t *));
235 if (walt_digits
!= NULL
)
237 const wchar_t *ptr
= _NL_CURRENT_WSTR (LC_TIME
, _NL_WALT_DIGITS
);
240 for (cnt
= 0; cnt
< 100; ++cnt
)
242 walt_digits
[cnt
] = ptr
;
244 /* Skip digit format. */
245 ptr
= wcschr (ptr
, L
'\0') + 1;
250 result
= walt_digits
!= NULL
&& number
< 100 ? walt_digits
[number
] : NULL
;
252 __libc_lock_unlock (__libc_setlocale_lock
);
254 return (wchar_t *) result
;
259 _nl_parse_alt_digit (const char **strp
)
261 const char *str
= *strp
;
266 __libc_lock_lock (__libc_setlocale_lock
);
268 if (alt_digits_initialized
== 0)
270 alt_digits_initialized
= 1;
272 if (alt_digits
== NULL
)
273 alt_digits
= malloc (100 * sizeof (const char *));
275 if (alt_digits
!= NULL
)
277 const char *ptr
= _NL_CURRENT (LC_TIME
, ALT_DIGITS
);
279 if (alt_digits
!= NULL
)
280 for (cnt
= 0; cnt
< 100; ++cnt
)
282 alt_digits
[cnt
] = ptr
;
284 /* Skip digit format. */
285 ptr
= strchr (ptr
, '\0') + 1;
290 /* Matching is not unambiguos. The alternative digits could be like
291 I, II, III, ... and the first one is a substring of the second
292 and third. Therefore we must keep on searching until we found
293 the longest possible match. Note that this is not specified in
295 for (cnt
= 0; cnt
< 100; ++cnt
)
297 size_t len
= strlen (alt_digits
[cnt
]);
299 if (len
> maxlen
&& strncmp (alt_digits
[cnt
], str
, len
) == 0)
306 __libc_lock_unlock (__libc_setlocale_lock
);
321 text_set_element (__libc_subfreeres
, free_mem
);