Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/nl_langinfo.c |
Source code | Switch to Preprocessed file |
Line | Source | Count |
---|---|---|
1 | /* nl_langinfo() replacement: query locale dependent information. | - |
2 | - | |
3 | Copyright (C) 2007-2018 Free Software Foundation, Inc. | - |
4 | - | |
5 | This program is free software: you can redistribute it and/or modify | - |
6 | it under the terms of the GNU General Public License as published by | - |
7 | the Free Software Foundation; either version 3 of the License, or | - |
8 | (at your option) any later version. | - |
9 | - | |
10 | This program 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 | - |
13 | GNU General Public License for more details. | - |
14 | - | |
15 | You should have received a copy of the GNU General Public License | - |
16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - |
17 | - | |
18 | #include <config.h> | - |
19 | - | |
20 | /* Specification. */ | - |
21 | #include <langinfo.h> | - |
22 | - | |
23 | #include <locale.h> | - |
24 | #include <string.h> | - |
25 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | - |
26 | # define WIN32_LEAN_AND_MEAN /* avoid including junk */ | - |
27 | # include <windows.h> | - |
28 | # include <stdio.h> | - |
29 | #endif | - |
30 | - | |
31 | #if !REPLACE_NL_LANGINFO || GNULIB_defined_CODESET | - |
32 | /* Return the codeset of the current locale, if this is easily deducible. | - |
33 | Otherwise, return "". */ | - |
34 | static char * | - |
35 | ctype_codeset (void) | - |
36 | { | - |
37 | static char buf[2 + 10 + 1]; | - |
38 | char const *locale = setlocale (LC_CTYPE, NULL); | - |
39 | char *codeset = buf; | - |
40 | size_t codesetlen; | - |
41 | codeset[0] = '\0'; | - |
42 | - | |
43 | if (locale && locale[0]) | - |
44 | { | - |
45 | /* If the locale name contains an encoding after the dot, return it. */ | - |
46 | char *dot = strchr (locale, '.'); | - |
47 | - | |
48 | if (dot) | - |
49 | { | - |
50 | /* Look for the possible @... trailer and remove it, if any. */ | - |
51 | char *codeset_start = dot + 1; | - |
52 | char const *modifier = strchr (codeset_start, '@'); | - |
53 | - | |
54 | if (! modifier) | - |
55 | codeset = codeset_start; | - |
56 | else | - |
57 | { | - |
58 | codesetlen = modifier - codeset_start; | - |
59 | if (codesetlen < sizeof buf) | - |
60 | { | - |
61 | codeset = memcpy (buf, codeset_start, codesetlen); | - |
62 | codeset[codesetlen] = '\0'; | - |
63 | } | - |
64 | } | - |
65 | } | - |
66 | } | - |
67 | - | |
68 | # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | - |
69 | /* If setlocale is successful, it returns the number of the | - |
70 | codepage, as a string. Otherwise, fall back on Windows API | - |
71 | GetACP, which returns the locale's codepage as a number (although | - |
72 | this doesn't change according to what the 'setlocale' call specified). | - |
73 | Either way, prepend "CP" to make it a valid codeset name. */ | - |
74 | codesetlen = strlen (codeset); | - |
75 | if (0 < codesetlen && codesetlen < sizeof buf - 2) | - |
76 | memmove (buf + 2, codeset, codesetlen + 1); | - |
77 | else | - |
78 | sprintf (buf + 2, "%u", GetACP ()); | - |
79 | codeset = memcpy (buf, "CP", 2); | - |
80 | # endif | - |
81 | return codeset; | - |
82 | } | - |
83 | #endif | - |
84 | - | |
85 | - | |
86 | #if REPLACE_NL_LANGINFO | - |
87 | - | |
88 | /* Override nl_langinfo with support for added nl_item values. */ | - |
89 | - | |
90 | # undef nl_langinfo | - |
91 | - | |
92 | char * | - |
93 | rpl_nl_langinfo (nl_item item) | - |
94 | { | - |
95 | switch (item) | - |
96 | { | - |
97 | # if GNULIB_defined_CODESET | - |
98 | case CODESET: | - |
99 | return ctype_codeset (); | - |
100 | # endif | - |
101 | # if GNULIB_defined_T_FMT_AMPM | - |
102 | case T_FMT_AMPM: | - |
103 | return (char *) "%I:%M:%S %p"; | - |
104 | # endif | - |
105 | # if GNULIB_defined_ALTMON | - |
106 | case ALTMON_1: never executed: case 10200 : | 0 |
107 | case ALTMON_2: never executed: case (10200 + 1) : | 0 |
108 | case ALTMON_3: never executed: case (10200 + 2) : | 0 |
109 | case ALTMON_4: never executed: case (10200 + 3) : | 0 |
110 | case ALTMON_5: never executed: case (10200 + 4) : | 0 |
111 | case ALTMON_6: never executed: case (10200 + 5) : | 0 |
112 | case ALTMON_7: never executed: case (10200 + 6) : | 0 |
113 | case ALTMON_8: never executed: case (10200 + 7) : | 0 |
114 | case ALTMON_9: never executed: case (10200 + 8) : | 0 |
115 | case ALTMON_10: never executed: case (10200 + 9) : | 0 |
116 | case ALTMON_11: never executed: case (10200 + 10) : | 0 |
117 | case ALTMON_12: never executed: case (10200 + 11) : | 0 |
118 | /* We don't ship the appropriate localizations with gnulib. Therefore, | - |
119 | treat ALTMON_i like MON_i. */ | - |
120 | item = item - ALTMON_1 + MON_1; | - |
121 | break; never executed: break; | 0 |
122 | # endif | - |
123 | # if GNULIB_defined_ERA | - |
124 | case ERA: | - |
125 | /* The format is not standardized. In glibc it is a sequence of strings | - |
126 | of the form "direction:offset:start_date:end_date:era_name:era_format" | - |
127 | with an empty string at the end. */ | - |
128 | return (char *) ""; | - |
129 | case ERA_D_FMT: | - |
130 | /* The %Ex conversion in strftime behaves like %x if the locale does not | - |
131 | have an alternative time format. */ | - |
132 | item = D_FMT; | - |
133 | break; | - |
134 | case ERA_D_T_FMT: | - |
135 | /* The %Ec conversion in strftime behaves like %c if the locale does not | - |
136 | have an alternative time format. */ | - |
137 | item = D_T_FMT; | - |
138 | break; | - |
139 | case ERA_T_FMT: | - |
140 | /* The %EX conversion in strftime behaves like %X if the locale does not | - |
141 | have an alternative time format. */ | - |
142 | item = T_FMT; | - |
143 | break; | - |
144 | case ALT_DIGITS: | - |
145 | /* The format is not standardized. In glibc it is a sequence of 10 | - |
146 | strings, appended in memory. */ | - |
147 | return (char *) "\0\0\0\0\0\0\0\0\0\0"; | - |
148 | # endif | - |
149 | # if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS | - |
150 | case YESEXPR: | - |
151 | return (char *) "^[yY]"; | - |
152 | case NOEXPR: | - |
153 | return (char *) "^[nN]"; | - |
154 | # endif | - |
155 | default: executed 5506 times by 58 tests: default: Executed by:
| 5506 |
156 | break; executed 5506 times by 58 tests: break; Executed by:
| 5506 |
157 | } | - |
158 | return nl_langinfo (item); executed 5506 times by 58 tests: return nl_langinfo (item); Executed by:
| 5506 |
159 | } | - |
160 | - | |
161 | #else | - |
162 | - | |
163 | /* Provide nl_langinfo from scratch, either for native MS-Windows, or | - |
164 | for old Unix platforms without locales, such as Linux libc5 or | - |
165 | BeOS. */ | - |
166 | - | |
167 | # include <time.h> | - |
168 | - | |
169 | char * | - |
170 | nl_langinfo (nl_item item) | - |
171 | { | - |
172 | static char nlbuf[100]; | - |
173 | struct tm tmm = { 0 }; | - |
174 | - | |
175 | switch (item) | - |
176 | { | - |
177 | /* nl_langinfo items of the LC_CTYPE category */ | - |
178 | case CODESET: | - |
179 | { | - |
180 | char *codeset = ctype_codeset (); | - |
181 | if (*codeset) | - |
182 | return codeset; | - |
183 | } | - |
184 | # ifdef __BEOS__ | - |
185 | return (char *) "UTF-8"; | - |
186 | # else | - |
187 | return (char *) "ISO-8859-1"; | - |
188 | # endif | - |
189 | /* nl_langinfo items of the LC_NUMERIC category */ | - |
190 | case RADIXCHAR: | - |
191 | return localeconv () ->decimal_point; | - |
192 | case THOUSEP: | - |
193 | return localeconv () ->thousands_sep; | - |
194 | case GROUPING: | - |
195 | return localeconv () ->grouping; | - |
196 | /* nl_langinfo items of the LC_TIME category. | - |
197 | TODO: Really use the locale. */ | - |
198 | case D_T_FMT: | - |
199 | case ERA_D_T_FMT: | - |
200 | return (char *) "%a %b %e %H:%M:%S %Y"; | - |
201 | case D_FMT: | - |
202 | case ERA_D_FMT: | - |
203 | return (char *) "%m/%d/%y"; | - |
204 | case T_FMT: | - |
205 | case ERA_T_FMT: | - |
206 | return (char *) "%H:%M:%S"; | - |
207 | case T_FMT_AMPM: | - |
208 | return (char *) "%I:%M:%S %p"; | - |
209 | case AM_STR: | - |
210 | if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm)) | - |
211 | return (char *) "AM"; | - |
212 | return nlbuf; | - |
213 | case PM_STR: | - |
214 | tmm.tm_hour = 12; | - |
215 | if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm)) | - |
216 | return (char *) "PM"; | - |
217 | return nlbuf; | - |
218 | case DAY_1: | - |
219 | case DAY_2: | - |
220 | case DAY_3: | - |
221 | case DAY_4: | - |
222 | case DAY_5: | - |
223 | case DAY_6: | - |
224 | case DAY_7: | - |
225 | { | - |
226 | static char const days[][sizeof "Wednesday"] = { | - |
227 | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", | - |
228 | "Friday", "Saturday" | - |
229 | }; | - |
230 | tmm.tm_wday = item - DAY_1; | - |
231 | if (!strftime (nlbuf, sizeof nlbuf, "%A", &tmm)) | - |
232 | return (char *) days[item - DAY_1]; | - |
233 | return nlbuf; | - |
234 | } | - |
235 | case ABDAY_1: | - |
236 | case ABDAY_2: | - |
237 | case ABDAY_3: | - |
238 | case ABDAY_4: | - |
239 | case ABDAY_5: | - |
240 | case ABDAY_6: | - |
241 | case ABDAY_7: | - |
242 | { | - |
243 | static char const abdays[][sizeof "Sun"] = { | - |
244 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" | - |
245 | }; | - |
246 | tmm.tm_wday = item - ABDAY_1; | - |
247 | if (!strftime (nlbuf, sizeof nlbuf, "%a", &tmm)) | - |
248 | return (char *) abdays[item - ABDAY_1]; | - |
249 | return nlbuf; | - |
250 | } | - |
251 | { | - |
252 | static char const months[][sizeof "September"] = { | - |
253 | "January", "February", "March", "April", "May", "June", "July", | - |
254 | "September", "October", "November", "December" | - |
255 | }; | - |
256 | case MON_1: | - |
257 | case MON_2: | - |
258 | case MON_3: | - |
259 | case MON_4: | - |
260 | case MON_5: | - |
261 | case MON_6: | - |
262 | case MON_7: | - |
263 | case MON_8: | - |
264 | case MON_9: | - |
265 | case MON_10: | - |
266 | case MON_11: | - |
267 | case MON_12: | - |
268 | tmm.tm_mon = item - MON_1; | - |
269 | if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm)) | - |
270 | return (char *) months[item - MON_1]; | - |
271 | return nlbuf; | - |
272 | case ALTMON_1: | - |
273 | case ALTMON_2: | - |
274 | case ALTMON_3: | - |
275 | case ALTMON_4: | - |
276 | case ALTMON_5: | - |
277 | case ALTMON_6: | - |
278 | case ALTMON_7: | - |
279 | case ALTMON_8: | - |
280 | case ALTMON_9: | - |
281 | case ALTMON_10: | - |
282 | case ALTMON_11: | - |
283 | case ALTMON_12: | - |
284 | tmm.tm_mon = item - ALTMON_1; | - |
285 | /* The platforms without nl_langinfo() don't support strftime with %OB. | - |
286 | We don't even need to try. */ | - |
287 | #if 0 | - |
288 | if (!strftime (nlbuf, sizeof nlbuf, "%OB", &tmm)) | - |
289 | #endif | - |
290 | if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm)) | - |
291 | return (char *) months[item - ALTMON_1]; | - |
292 | return nlbuf; | - |
293 | } | - |
294 | case ABMON_1: | - |
295 | case ABMON_2: | - |
296 | case ABMON_3: | - |
297 | case ABMON_4: | - |
298 | case ABMON_5: | - |
299 | case ABMON_6: | - |
300 | case ABMON_7: | - |
301 | case ABMON_8: | - |
302 | case ABMON_9: | - |
303 | case ABMON_10: | - |
304 | case ABMON_11: | - |
305 | case ABMON_12: | - |
306 | { | - |
307 | static char const abmonths[][sizeof "Jan"] = { | - |
308 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", | - |
309 | "Sep", "Oct", "Nov", "Dec" | - |
310 | }; | - |
311 | tmm.tm_mon = item - ABMON_1; | - |
312 | if (!strftime (nlbuf, sizeof nlbuf, "%b", &tmm)) | - |
313 | return (char *) abmonths[item - ABMON_1]; | - |
314 | return nlbuf; | - |
315 | } | - |
316 | case ERA: | - |
317 | return (char *) ""; | - |
318 | case ALT_DIGITS: | - |
319 | return (char *) "\0\0\0\0\0\0\0\0\0\0"; | - |
320 | /* nl_langinfo items of the LC_MONETARY category. */ | - |
321 | case CRNCYSTR: | - |
322 | return localeconv () ->currency_symbol; | - |
323 | case INT_CURR_SYMBOL: | - |
324 | return localeconv () ->int_curr_symbol; | - |
325 | case MON_DECIMAL_POINT: | - |
326 | return localeconv () ->mon_decimal_point; | - |
327 | case MON_THOUSANDS_SEP: | - |
328 | return localeconv () ->mon_thousands_sep; | - |
329 | case MON_GROUPING: | - |
330 | return localeconv () ->mon_grouping; | - |
331 | case POSITIVE_SIGN: | - |
332 | return localeconv () ->positive_sign; | - |
333 | case NEGATIVE_SIGN: | - |
334 | return localeconv () ->negative_sign; | - |
335 | case FRAC_DIGITS: | - |
336 | return & localeconv () ->frac_digits; | - |
337 | case INT_FRAC_DIGITS: | - |
338 | return & localeconv () ->int_frac_digits; | - |
339 | case P_CS_PRECEDES: | - |
340 | return & localeconv () ->p_cs_precedes; | - |
341 | case N_CS_PRECEDES: | - |
342 | return & localeconv () ->n_cs_precedes; | - |
343 | case P_SEP_BY_SPACE: | - |
344 | return & localeconv () ->p_sep_by_space; | - |
345 | case N_SEP_BY_SPACE: | - |
346 | return & localeconv () ->n_sep_by_space; | - |
347 | case P_SIGN_POSN: | - |
348 | return & localeconv () ->p_sign_posn; | - |
349 | case N_SIGN_POSN: | - |
350 | return & localeconv () ->n_sign_posn; | - |
351 | /* nl_langinfo items of the LC_MESSAGES category | - |
352 | TODO: Really use the locale. */ | - |
353 | case YESEXPR: | - |
354 | return (char *) "^[yY]"; | - |
355 | case NOEXPR: | - |
356 | return (char *) "^[nN]"; | - |
357 | default: | - |
358 | return (char *) ""; | - |
359 | } | - |
360 | } | - |
361 | - | |
362 | #endif | - |
Source code | Switch to Preprocessed file |