1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Research
26da2e3ebdSchin *
27da2e3ebdSchin * time conversion translation support
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #include <ast.h>
31da2e3ebdSchin #include <cdt.h>
32da2e3ebdSchin #include <iconv.h>
33da2e3ebdSchin #include <mc.h>
34da2e3ebdSchin #include <tm.h>
35*3e14f97fSRoger A. Faulkner #include <ast_nl_types.h>
36da2e3ebdSchin
37da2e3ebdSchin #include "lclib.h"
38da2e3ebdSchin
39da2e3ebdSchin static struct
40da2e3ebdSchin {
41da2e3ebdSchin char* format;
42da2e3ebdSchin Lc_info_t* locale;
43da2e3ebdSchin char null[1];
44da2e3ebdSchin } state;
45da2e3ebdSchin
46da2e3ebdSchin /*
47da2e3ebdSchin * this is unix dadgummit
48da2e3ebdSchin */
49da2e3ebdSchin
50da2e3ebdSchin static int
standardized(Lc_info_t * li,register char ** b)51da2e3ebdSchin standardized(Lc_info_t* li, register char** b)
52da2e3ebdSchin {
53da2e3ebdSchin if ((li->lc->language->flags & (LC_debug|LC_default)) || streq(li->lc->language->code, "en"))
54da2e3ebdSchin {
55da2e3ebdSchin b[TM_TIME] = "%H:%M:%S";
56da2e3ebdSchin b[TM_DATE] = "%m/%d/%y";
57da2e3ebdSchin b[TM_DEFAULT] = "%a %b %e %T %Z %Y";
58da2e3ebdSchin return 1;
59da2e3ebdSchin }
60da2e3ebdSchin return 0;
61da2e3ebdSchin }
62da2e3ebdSchin
63da2e3ebdSchin /*
64da2e3ebdSchin * fix up LC_TIME data after loading
65da2e3ebdSchin */
66da2e3ebdSchin
67da2e3ebdSchin static void
fixup(Lc_info_t * li,register char ** b)68da2e3ebdSchin fixup(Lc_info_t* li, register char** b)
69da2e3ebdSchin {
70da2e3ebdSchin register char** v;
71da2e3ebdSchin register char** e;
72da2e3ebdSchin register int n;
73da2e3ebdSchin
74da2e3ebdSchin static int must[] =
75da2e3ebdSchin {
76da2e3ebdSchin TM_TIME,
77da2e3ebdSchin TM_DATE,
78da2e3ebdSchin TM_DEFAULT,
79da2e3ebdSchin TM_CTIME,
80da2e3ebdSchin TM_DATE_1,
81da2e3ebdSchin TM_INTERNATIONAL,
82da2e3ebdSchin TM_RECENT,
83da2e3ebdSchin TM_DISTANT,
84da2e3ebdSchin TM_MERIDIAN_TIME,
85da2e3ebdSchin };
86da2e3ebdSchin
87da2e3ebdSchin standardized(li, b);
88da2e3ebdSchin for (v = b, e = b + TM_NFORM; v < e; v++)
89da2e3ebdSchin if (!*v)
90da2e3ebdSchin *v = state.null;
91da2e3ebdSchin for (n = 0; n < elementsof(must); n++)
92da2e3ebdSchin if (!*b[must[n]])
93da2e3ebdSchin b[must[n]] = tm_data.format[must[n]];
94da2e3ebdSchin if (li->lc->flags & LC_default)
95da2e3ebdSchin for (n = 0; n < TM_NFORM; n++)
96da2e3ebdSchin if (!*b[n])
97da2e3ebdSchin b[n] = tm_data.format[n];
98da2e3ebdSchin if (strchr(b[TM_UT], '%'))
99da2e3ebdSchin {
100da2e3ebdSchin tm_info.deformat = b[TM_UT];
101da2e3ebdSchin for (n = TM_UT; n < TM_DT; n++)
102da2e3ebdSchin b[n] = state.null;
103da2e3ebdSchin }
104da2e3ebdSchin else
105da2e3ebdSchin tm_info.deformat = b[TM_DEFAULT];
106da2e3ebdSchin tm_info.format = b;
107da2e3ebdSchin if (!(tm_info.deformat = state.format))
108da2e3ebdSchin tm_info.deformat = tm_info.format[TM_DEFAULT];
109da2e3ebdSchin li->data = (void*)b;
110da2e3ebdSchin }
111da2e3ebdSchin
112da2e3ebdSchin #if _WINIX
113da2e3ebdSchin
114da2e3ebdSchin #include <ast_windows.h>
115da2e3ebdSchin
116da2e3ebdSchin typedef struct Map_s
117da2e3ebdSchin {
118da2e3ebdSchin LCID native;
119da2e3ebdSchin int local;
120da2e3ebdSchin } Map_t;
121da2e3ebdSchin
122da2e3ebdSchin static const Map_t map[] =
123da2e3ebdSchin {
124da2e3ebdSchin LOCALE_S1159, (TM_MERIDIAN+0),
125da2e3ebdSchin LOCALE_S2359, (TM_MERIDIAN+1),
126da2e3ebdSchin LOCALE_SABBREVDAYNAME1, (TM_DAY_ABBREV+1),
127da2e3ebdSchin LOCALE_SABBREVDAYNAME2, (TM_DAY_ABBREV+2),
128da2e3ebdSchin LOCALE_SABBREVDAYNAME3, (TM_DAY_ABBREV+3),
129da2e3ebdSchin LOCALE_SABBREVDAYNAME4, (TM_DAY_ABBREV+4),
130da2e3ebdSchin LOCALE_SABBREVDAYNAME5, (TM_DAY_ABBREV+5),
131da2e3ebdSchin LOCALE_SABBREVDAYNAME6, (TM_DAY_ABBREV+6),
132da2e3ebdSchin LOCALE_SABBREVDAYNAME7, (TM_DAY_ABBREV+0),
133da2e3ebdSchin LOCALE_SABBREVMONTHNAME1, (TM_MONTH_ABBREV+0),
134da2e3ebdSchin LOCALE_SABBREVMONTHNAME2, (TM_MONTH_ABBREV+1),
135da2e3ebdSchin LOCALE_SABBREVMONTHNAME3, (TM_MONTH_ABBREV+2),
136da2e3ebdSchin LOCALE_SABBREVMONTHNAME4, (TM_MONTH_ABBREV+3),
137da2e3ebdSchin LOCALE_SABBREVMONTHNAME5, (TM_MONTH_ABBREV+4),
138da2e3ebdSchin LOCALE_SABBREVMONTHNAME6, (TM_MONTH_ABBREV+5),
139da2e3ebdSchin LOCALE_SABBREVMONTHNAME7, (TM_MONTH_ABBREV+6),
140da2e3ebdSchin LOCALE_SABBREVMONTHNAME8, (TM_MONTH_ABBREV+7),
141da2e3ebdSchin LOCALE_SABBREVMONTHNAME9, (TM_MONTH_ABBREV+8),
142da2e3ebdSchin LOCALE_SABBREVMONTHNAME10, (TM_MONTH_ABBREV+9),
143da2e3ebdSchin LOCALE_SABBREVMONTHNAME11, (TM_MONTH_ABBREV+10),
144da2e3ebdSchin LOCALE_SABBREVMONTHNAME12, (TM_MONTH_ABBREV+11),
145da2e3ebdSchin LOCALE_SDAYNAME1, (TM_DAY+1),
146da2e3ebdSchin LOCALE_SDAYNAME2, (TM_DAY+2),
147da2e3ebdSchin LOCALE_SDAYNAME3, (TM_DAY+3),
148da2e3ebdSchin LOCALE_SDAYNAME4, (TM_DAY+4),
149da2e3ebdSchin LOCALE_SDAYNAME5, (TM_DAY+5),
150da2e3ebdSchin LOCALE_SDAYNAME6, (TM_DAY+6),
151da2e3ebdSchin LOCALE_SDAYNAME7, (TM_DAY+0),
152da2e3ebdSchin LOCALE_SMONTHNAME1, (TM_MONTH+0),
153da2e3ebdSchin LOCALE_SMONTHNAME2, (TM_MONTH+1),
154da2e3ebdSchin LOCALE_SMONTHNAME3, (TM_MONTH+2),
155da2e3ebdSchin LOCALE_SMONTHNAME4, (TM_MONTH+3),
156da2e3ebdSchin LOCALE_SMONTHNAME5, (TM_MONTH+4),
157da2e3ebdSchin LOCALE_SMONTHNAME6, (TM_MONTH+5),
158da2e3ebdSchin LOCALE_SMONTHNAME7, (TM_MONTH+6),
159da2e3ebdSchin LOCALE_SMONTHNAME8, (TM_MONTH+7),
160da2e3ebdSchin LOCALE_SMONTHNAME9, (TM_MONTH+8),
161da2e3ebdSchin LOCALE_SMONTHNAME10, (TM_MONTH+9),
162da2e3ebdSchin LOCALE_SMONTHNAME11, (TM_MONTH+10),
163da2e3ebdSchin LOCALE_SMONTHNAME12, (TM_MONTH+11),
164da2e3ebdSchin };
165da2e3ebdSchin
166da2e3ebdSchin #undef extern
167da2e3ebdSchin
168da2e3ebdSchin /*
169da2e3ebdSchin * convert ms word date spec w to posix strftime format f
170da2e3ebdSchin * next char after f returned
171da2e3ebdSchin * the caller already made sure f is big enough
172da2e3ebdSchin */
173da2e3ebdSchin
174da2e3ebdSchin static char*
word2posix(register char * f,register char * w,int alternate)175da2e3ebdSchin word2posix(register char* f, register char* w, int alternate)
176da2e3ebdSchin {
177da2e3ebdSchin register char* r;
178da2e3ebdSchin register int c;
179da2e3ebdSchin register int p;
180da2e3ebdSchin register int n;
181da2e3ebdSchin
182da2e3ebdSchin while (*w)
183da2e3ebdSchin {
184da2e3ebdSchin p = 0;
185da2e3ebdSchin r = w;
186da2e3ebdSchin while (*++w == *r);
187da2e3ebdSchin if ((n = w - r) > 3 && alternate)
188da2e3ebdSchin n--;
189da2e3ebdSchin switch (*r)
190da2e3ebdSchin {
191da2e3ebdSchin case 'a':
192da2e3ebdSchin case 'A':
193da2e3ebdSchin if (!strncasecmp(w, "am/pm", 5))
194da2e3ebdSchin w += 5;
195da2e3ebdSchin else if (!strncasecmp(w, "a/p", 3))
196da2e3ebdSchin w += 3;
197da2e3ebdSchin c = 'p';
198da2e3ebdSchin break;
199da2e3ebdSchin case 'd':
200da2e3ebdSchin switch (n)
201da2e3ebdSchin {
202da2e3ebdSchin case 1:
203da2e3ebdSchin p = '-';
204da2e3ebdSchin /*FALLTHROUGH*/
205da2e3ebdSchin case 2:
206da2e3ebdSchin c = 'd';
207da2e3ebdSchin break;
208da2e3ebdSchin case 3:
209da2e3ebdSchin c = 'a';
210da2e3ebdSchin break;
211da2e3ebdSchin default:
212da2e3ebdSchin c = 'A';
213da2e3ebdSchin break;
214da2e3ebdSchin }
215da2e3ebdSchin break;
216da2e3ebdSchin case 'h':
217da2e3ebdSchin switch (n)
218da2e3ebdSchin {
219da2e3ebdSchin case 1:
220da2e3ebdSchin p = '-';
221da2e3ebdSchin /*FALLTHROUGH*/
222da2e3ebdSchin default:
223da2e3ebdSchin c = 'I';
224da2e3ebdSchin break;
225da2e3ebdSchin }
226da2e3ebdSchin break;
227da2e3ebdSchin case 'H':
228da2e3ebdSchin switch (n)
229da2e3ebdSchin {
230da2e3ebdSchin case 1:
231da2e3ebdSchin p = '-';
232da2e3ebdSchin /*FALLTHROUGH*/
233da2e3ebdSchin default:
234da2e3ebdSchin c = 'H';
235da2e3ebdSchin break;
236da2e3ebdSchin }
237da2e3ebdSchin break;
238da2e3ebdSchin case 'M':
239da2e3ebdSchin switch (n)
240da2e3ebdSchin {
241da2e3ebdSchin case 1:
242da2e3ebdSchin p = '-';
243da2e3ebdSchin /*FALLTHROUGH*/
244da2e3ebdSchin case 2:
245da2e3ebdSchin c = 'm';
246da2e3ebdSchin break;
247da2e3ebdSchin case 3:
248da2e3ebdSchin c = 'b';
249da2e3ebdSchin break;
250da2e3ebdSchin default:
251da2e3ebdSchin c = 'B';
252da2e3ebdSchin break;
253da2e3ebdSchin }
254da2e3ebdSchin break;
255da2e3ebdSchin case 'm':
256da2e3ebdSchin switch (n)
257da2e3ebdSchin {
258da2e3ebdSchin case 1:
259da2e3ebdSchin p = '-';
260da2e3ebdSchin /*FALLTHROUGH*/
261da2e3ebdSchin default:
262da2e3ebdSchin c = 'M';
263da2e3ebdSchin break;
264da2e3ebdSchin }
265da2e3ebdSchin break;
266da2e3ebdSchin case 's':
267da2e3ebdSchin switch (n)
268da2e3ebdSchin {
269da2e3ebdSchin case 1:
270da2e3ebdSchin p = '-';
271da2e3ebdSchin /*FALLTHROUGH*/
272da2e3ebdSchin default:
273da2e3ebdSchin c = 'S';
274da2e3ebdSchin break;
275da2e3ebdSchin }
276da2e3ebdSchin break;
277da2e3ebdSchin case 'y':
278da2e3ebdSchin switch (n)
279da2e3ebdSchin {
280da2e3ebdSchin case 1:
281da2e3ebdSchin p = '-';
282da2e3ebdSchin /*FALLTHROUGH*/
283da2e3ebdSchin case 2:
284da2e3ebdSchin c = 'y';
285da2e3ebdSchin break;
286da2e3ebdSchin default:
287da2e3ebdSchin c = 'Y';
288da2e3ebdSchin break;
289da2e3ebdSchin }
290da2e3ebdSchin break;
291da2e3ebdSchin case '\'':
292da2e3ebdSchin if (n & 1)
293da2e3ebdSchin for (w = r + 1; *w; *f++ = *w++)
294da2e3ebdSchin if (*w == '\'')
295da2e3ebdSchin {
296da2e3ebdSchin w++;
297da2e3ebdSchin break;
298da2e3ebdSchin }
299da2e3ebdSchin continue;
300da2e3ebdSchin case '%':
301da2e3ebdSchin while (r < w)
302da2e3ebdSchin {
303da2e3ebdSchin *f++ = *r++;
304da2e3ebdSchin *f++ = *r++;
305da2e3ebdSchin }
306da2e3ebdSchin continue;
307da2e3ebdSchin default:
308da2e3ebdSchin while (r < w)
309da2e3ebdSchin *f++ = *r++;
310da2e3ebdSchin continue;
311da2e3ebdSchin }
312da2e3ebdSchin *f++ = '%';
313da2e3ebdSchin if (p)
314da2e3ebdSchin *f++ = '-';
315da2e3ebdSchin *f++ = c;
316da2e3ebdSchin }
317da2e3ebdSchin *f++ = 0;
318da2e3ebdSchin return f;
319da2e3ebdSchin }
320da2e3ebdSchin
321da2e3ebdSchin /*
322da2e3ebdSchin * load the native LC_TIME data for the current locale
323da2e3ebdSchin */
324da2e3ebdSchin
325da2e3ebdSchin static void
native_lc_time(Lc_info_t * li)326da2e3ebdSchin native_lc_time(Lc_info_t* li)
327da2e3ebdSchin {
328da2e3ebdSchin register char* s;
329da2e3ebdSchin register char* t;
330da2e3ebdSchin register char** b;
331da2e3ebdSchin register int n;
332da2e3ebdSchin register int m;
333da2e3ebdSchin register int i;
334da2e3ebdSchin LCID lcid;
335da2e3ebdSchin int nt;
336da2e3ebdSchin int ns;
337da2e3ebdSchin int nl;
338da2e3ebdSchin int clock_24;
339da2e3ebdSchin int leading_0;
340da2e3ebdSchin char buf[256];
341da2e3ebdSchin
342da2e3ebdSchin lcid = li->lc->index;
343da2e3ebdSchin nt = 2 * GetLocaleInfo(lcid, LOCALE_STIME, 0, 0) + 7; /* HH:MM:SS */
344da2e3ebdSchin ns = 3 * GetLocaleInfo(lcid, LOCALE_SSHORTDATE, 0, 0);
345da2e3ebdSchin nl = 3 * GetLocaleInfo(lcid, LOCALE_SLONGDATE, 0, 0);
346da2e3ebdSchin n = nt + ns + nl;
347da2e3ebdSchin for (i = 0; i < elementsof(map); i++)
348da2e3ebdSchin n += GetLocaleInfo(lcid, map[i].native, 0, 0);
349da2e3ebdSchin if (!(b = newof(0, char*, TM_NFORM, n)))
350da2e3ebdSchin return;
351da2e3ebdSchin s = (char*)(b + TM_NFORM);
352da2e3ebdSchin for (i = 0; i < elementsof(map); i++)
353da2e3ebdSchin {
354da2e3ebdSchin if (!(m = GetLocaleInfo(lcid, map[i].native, s, n)))
355da2e3ebdSchin goto bad;
356da2e3ebdSchin b[map[i].local] = s;
357da2e3ebdSchin s += m;
358da2e3ebdSchin }
359da2e3ebdSchin if (!standardized(li, b))
360da2e3ebdSchin {
361da2e3ebdSchin /*
362da2e3ebdSchin * synthesize TM_TIME format from the ms word template
363da2e3ebdSchin */
364da2e3ebdSchin
365da2e3ebdSchin if (!GetLocaleInfo(lcid, LOCALE_ITIME, buf, sizeof(buf)))
366da2e3ebdSchin goto bad;
367da2e3ebdSchin clock_24 = atoi(buf);
368da2e3ebdSchin if (!GetLocaleInfo(lcid, LOCALE_ITLZERO, buf, sizeof(buf)))
369da2e3ebdSchin goto bad;
370da2e3ebdSchin leading_0 = atoi(buf);
371da2e3ebdSchin if (!GetLocaleInfo(lcid, LOCALE_STIME, buf, sizeof(buf)))
372da2e3ebdSchin goto bad;
373da2e3ebdSchin b[TM_TIME] = s;
374da2e3ebdSchin *s++ = '%';
375da2e3ebdSchin if (!leading_0)
376da2e3ebdSchin *s++ = '-';
377da2e3ebdSchin *s++ = clock_24 ? 'H' : 'I';
378da2e3ebdSchin for (t = buf; *s = *t++; s++);
379da2e3ebdSchin *s++ = '%';
380da2e3ebdSchin if (!leading_0)
381da2e3ebdSchin *s++ = '-';
382da2e3ebdSchin *s++ = 'M';
383da2e3ebdSchin for (t = buf; *s = *t++; s++);
384da2e3ebdSchin *s++ = '%';
385da2e3ebdSchin if (!leading_0)
386da2e3ebdSchin *s++ = '-';
387da2e3ebdSchin *s++ = 'S';
388da2e3ebdSchin *s++ = 0;
389da2e3ebdSchin
390da2e3ebdSchin /*
391da2e3ebdSchin * synthesize TM_DATE format
392da2e3ebdSchin */
393da2e3ebdSchin
394da2e3ebdSchin if (!GetLocaleInfo(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)))
395da2e3ebdSchin goto bad;
396da2e3ebdSchin b[TM_DATE] = s;
397da2e3ebdSchin s = word2posix(s, buf, 1);
398da2e3ebdSchin
399da2e3ebdSchin /*
400da2e3ebdSchin * synthesize TM_DEFAULT format
401da2e3ebdSchin */
402da2e3ebdSchin
403da2e3ebdSchin if (!GetLocaleInfo(lcid, LOCALE_SLONGDATE, buf, sizeof(buf)))
404da2e3ebdSchin goto bad;
405da2e3ebdSchin b[TM_DEFAULT] = s;
406da2e3ebdSchin s = word2posix(s, buf, 1);
407da2e3ebdSchin strcpy(s - 1, " %X");
408da2e3ebdSchin }
409da2e3ebdSchin
410da2e3ebdSchin /*
411da2e3ebdSchin * done
412da2e3ebdSchin */
413da2e3ebdSchin
414da2e3ebdSchin fixup(li, b);
415da2e3ebdSchin return;
416da2e3ebdSchin bad:
417da2e3ebdSchin free(b);
418da2e3ebdSchin }
419da2e3ebdSchin
420da2e3ebdSchin #else
421da2e3ebdSchin
422da2e3ebdSchin #if _lib_nl_langinfo && _hdr_langinfo
423da2e3ebdSchin
424da2e3ebdSchin #if _hdr_nl_types
425da2e3ebdSchin #include <nl_types.h>
426da2e3ebdSchin #endif
427da2e3ebdSchin
428da2e3ebdSchin #include <langinfo.h>
429da2e3ebdSchin
430da2e3ebdSchin typedef struct Map_s
431da2e3ebdSchin {
432da2e3ebdSchin int native;
433da2e3ebdSchin int local;
434da2e3ebdSchin } Map_t;
435da2e3ebdSchin
436da2e3ebdSchin static const Map_t map[] =
437da2e3ebdSchin {
438da2e3ebdSchin AM_STR, (TM_MERIDIAN+0),
439da2e3ebdSchin PM_STR, (TM_MERIDIAN+1),
440da2e3ebdSchin ABDAY_1, (TM_DAY_ABBREV+0),
441da2e3ebdSchin ABDAY_2, (TM_DAY_ABBREV+1),
442da2e3ebdSchin ABDAY_3, (TM_DAY_ABBREV+2),
443da2e3ebdSchin ABDAY_4, (TM_DAY_ABBREV+3),
444da2e3ebdSchin ABDAY_5, (TM_DAY_ABBREV+4),
445da2e3ebdSchin ABDAY_6, (TM_DAY_ABBREV+5),
446da2e3ebdSchin ABDAY_7, (TM_DAY_ABBREV+6),
447da2e3ebdSchin ABMON_1, (TM_MONTH_ABBREV+0),
448da2e3ebdSchin ABMON_2, (TM_MONTH_ABBREV+1),
449da2e3ebdSchin ABMON_3, (TM_MONTH_ABBREV+2),
450da2e3ebdSchin ABMON_4, (TM_MONTH_ABBREV+3),
451da2e3ebdSchin ABMON_5, (TM_MONTH_ABBREV+4),
452da2e3ebdSchin ABMON_6, (TM_MONTH_ABBREV+5),
453da2e3ebdSchin ABMON_7, (TM_MONTH_ABBREV+6),
454da2e3ebdSchin ABMON_8, (TM_MONTH_ABBREV+7),
455da2e3ebdSchin ABMON_9, (TM_MONTH_ABBREV+8),
456da2e3ebdSchin ABMON_10, (TM_MONTH_ABBREV+9),
457da2e3ebdSchin ABMON_11, (TM_MONTH_ABBREV+10),
458da2e3ebdSchin ABMON_12, (TM_MONTH_ABBREV+11),
459da2e3ebdSchin DAY_1, (TM_DAY+0),
460da2e3ebdSchin DAY_2, (TM_DAY+1),
461da2e3ebdSchin DAY_3, (TM_DAY+2),
462da2e3ebdSchin DAY_4, (TM_DAY+3),
463da2e3ebdSchin DAY_5, (TM_DAY+4),
464da2e3ebdSchin DAY_6, (TM_DAY+5),
465da2e3ebdSchin DAY_7, (TM_DAY+6),
466da2e3ebdSchin MON_1, (TM_MONTH+0),
467da2e3ebdSchin MON_2, (TM_MONTH+1),
468da2e3ebdSchin MON_3, (TM_MONTH+2),
469da2e3ebdSchin MON_4, (TM_MONTH+3),
470da2e3ebdSchin MON_5, (TM_MONTH+4),
471da2e3ebdSchin MON_6, (TM_MONTH+5),
472da2e3ebdSchin MON_7, (TM_MONTH+6),
473da2e3ebdSchin MON_8, (TM_MONTH+7),
474da2e3ebdSchin MON_9, (TM_MONTH+8),
475da2e3ebdSchin MON_10, (TM_MONTH+9),
476da2e3ebdSchin MON_11, (TM_MONTH+10),
477da2e3ebdSchin MON_12, (TM_MONTH+11),
4787c2fbfb3SApril Chin #ifdef _DATE_FMT
4797c2fbfb3SApril Chin _DATE_FMT, TM_DEFAULT,
4807c2fbfb3SApril Chin #else
481da2e3ebdSchin D_T_FMT, TM_DEFAULT,
4827c2fbfb3SApril Chin #endif
483da2e3ebdSchin D_FMT, TM_DATE,
484da2e3ebdSchin T_FMT, TM_TIME,
485da2e3ebdSchin #ifdef ERA
486da2e3ebdSchin ERA, TM_ERA,
487da2e3ebdSchin ERA_D_T_FMT, TM_ERA_DEFAULT,
488da2e3ebdSchin ERA_D_FMT, TM_ERA_DATE,
489da2e3ebdSchin ERA_T_FMT, TM_ERA_TIME,
490da2e3ebdSchin #endif
491da2e3ebdSchin #ifdef ALT_DIGITS
492da2e3ebdSchin ALT_DIGITS, TM_DIGITS,
493da2e3ebdSchin #endif
494da2e3ebdSchin };
495da2e3ebdSchin
496da2e3ebdSchin static void
native_lc_time(Lc_info_t * li)497da2e3ebdSchin native_lc_time(Lc_info_t* li)
498da2e3ebdSchin {
499da2e3ebdSchin register char* s;
500da2e3ebdSchin register char* t;
501da2e3ebdSchin register char** b;
502da2e3ebdSchin register int n;
503da2e3ebdSchin register int i;
504da2e3ebdSchin
505da2e3ebdSchin n = 0;
506da2e3ebdSchin for (i = 0; i < elementsof(map); i++)
507*3e14f97fSRoger A. Faulkner {
508*3e14f97fSRoger A. Faulkner if (!(t = nl_langinfo(map[i].native)))
509*3e14f97fSRoger A. Faulkner t = tm_data.format[map[i].local];
510*3e14f97fSRoger A. Faulkner n += strlen(t) + 1;
511*3e14f97fSRoger A. Faulkner }
512da2e3ebdSchin if (!(b = newof(0, char*, TM_NFORM, n)))
513da2e3ebdSchin return;
514da2e3ebdSchin s = (char*)(b + TM_NFORM);
515da2e3ebdSchin for (i = 0; i < elementsof(map); i++)
516da2e3ebdSchin {
517da2e3ebdSchin b[map[i].local] = s;
518*3e14f97fSRoger A. Faulkner if (!(t = nl_langinfo(map[i].native)))
519*3e14f97fSRoger A. Faulkner t = tm_data.format[map[i].local];
520da2e3ebdSchin while (*s++ = *t++);
521da2e3ebdSchin }
522da2e3ebdSchin fixup(li, b);
523da2e3ebdSchin }
524da2e3ebdSchin
525da2e3ebdSchin #else
526da2e3ebdSchin
527da2e3ebdSchin #define native_lc_time(li) ((li->data=(void*)(tm_info.format=tm_data.format)),(tm_info.deformat=tm_info.format[TM_DEFAULT]))
528da2e3ebdSchin
529da2e3ebdSchin #endif
530da2e3ebdSchin
531da2e3ebdSchin #endif
532da2e3ebdSchin
533da2e3ebdSchin /*
534da2e3ebdSchin * load the LC_TIME data for the current locale
535da2e3ebdSchin */
536da2e3ebdSchin
537da2e3ebdSchin static void
load(Lc_info_t * li)538da2e3ebdSchin load(Lc_info_t* li)
539da2e3ebdSchin {
540da2e3ebdSchin register char* s;
541da2e3ebdSchin register char** b;
542da2e3ebdSchin register char** v;
543da2e3ebdSchin register char** e;
544da2e3ebdSchin unsigned char* u;
545da2e3ebdSchin ssize_t n;
546da2e3ebdSchin iconv_t cvt;
547da2e3ebdSchin Sfio_t* sp;
548da2e3ebdSchin Sfio_t* tp;
549da2e3ebdSchin char path[PATH_MAX];
550da2e3ebdSchin
551da2e3ebdSchin if (b = (char**)li->data)
552da2e3ebdSchin {
553da2e3ebdSchin tm_info.format = b;
554da2e3ebdSchin if (!(tm_info.deformat = state.format))
555da2e3ebdSchin tm_info.deformat = tm_info.format[TM_DEFAULT];
556da2e3ebdSchin return;
557da2e3ebdSchin }
558da2e3ebdSchin tm_info.format = tm_data.format;
559da2e3ebdSchin if (!(tm_info.deformat = state.format))
560da2e3ebdSchin tm_info.deformat = tm_info.format[TM_DEFAULT];
561da2e3ebdSchin if (mcfind(path, NiL, NiL, LC_TIME, 0) && (sp = sfopen(NiL, path, "r")))
562da2e3ebdSchin {
563da2e3ebdSchin n = sfsize(sp);
564da2e3ebdSchin tp = 0;
565da2e3ebdSchin if (u = (unsigned char*)sfreserve(sp, 3, 1))
566da2e3ebdSchin {
567da2e3ebdSchin if (u[0] == 0xef && u[1] == 0xbb && u[2] == 0xbf && (cvt = iconv_open("", "utf")) != (iconv_t)(-1))
568da2e3ebdSchin {
569da2e3ebdSchin if (tp = sfstropen())
570da2e3ebdSchin {
571da2e3ebdSchin sfread(sp, u, 3);
572da2e3ebdSchin n = iconv_move(cvt, sp, tp, SF_UNBOUND, NiL);
573da2e3ebdSchin }
574da2e3ebdSchin iconv_close(cvt);
575da2e3ebdSchin }
576da2e3ebdSchin if (!tp)
577da2e3ebdSchin sfread(sp, u, 0);
578da2e3ebdSchin }
579da2e3ebdSchin if (b = newof(0, char*, TM_NFORM, n + 2))
580da2e3ebdSchin {
581da2e3ebdSchin v = b;
582da2e3ebdSchin e = b + TM_NFORM;
583da2e3ebdSchin s = (char*)e;
584da2e3ebdSchin if (tp && memcpy(s, sfstrbase(tp), n) || !tp && sfread(sp, s, n) == n)
585da2e3ebdSchin {
586da2e3ebdSchin s[n] = '\n';
587da2e3ebdSchin while (v < e)
588da2e3ebdSchin {
589da2e3ebdSchin *v++ = s;
590da2e3ebdSchin if (!(s = strchr(s, '\n')))
591da2e3ebdSchin break;
592da2e3ebdSchin *s++ = 0;
593da2e3ebdSchin }
594da2e3ebdSchin fixup(li, b);
595da2e3ebdSchin }
596da2e3ebdSchin else
597da2e3ebdSchin free(b);
598da2e3ebdSchin }
599da2e3ebdSchin if (tp)
600da2e3ebdSchin sfclose(tp);
601da2e3ebdSchin sfclose(sp);
602da2e3ebdSchin }
603da2e3ebdSchin else
604da2e3ebdSchin native_lc_time(li);
605da2e3ebdSchin }
606da2e3ebdSchin
607da2e3ebdSchin /*
608da2e3ebdSchin * check that tm_info.format matches the current locale
609da2e3ebdSchin */
610da2e3ebdSchin
611da2e3ebdSchin char**
tmlocale(void)612da2e3ebdSchin tmlocale(void)
613da2e3ebdSchin {
614da2e3ebdSchin Lc_info_t* li;
615da2e3ebdSchin
616da2e3ebdSchin if (!tm_info.format)
617da2e3ebdSchin {
618da2e3ebdSchin tm_info.format = tm_data.format;
619da2e3ebdSchin if (!tm_info.deformat)
620da2e3ebdSchin tm_info.deformat = tm_info.format[TM_DEFAULT];
621da2e3ebdSchin else if (tm_info.deformat != tm_info.format[TM_DEFAULT])
622da2e3ebdSchin state.format = tm_info.deformat;
623da2e3ebdSchin }
624da2e3ebdSchin li = LCINFO(AST_LC_TIME);
625da2e3ebdSchin if (!li->data)
626da2e3ebdSchin load(li);
627da2e3ebdSchin return tm_info.format;
628da2e3ebdSchin }
629