14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*8462SApril.Chin@Sun.COM *          Copyright (c) 1985-2008 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
7*8462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * time conversion translation support
284887Schin  */
294887Schin 
304887Schin #include <ast.h>
314887Schin #include <cdt.h>
324887Schin #include <iconv.h>
334887Schin #include <mc.h>
344887Schin #include <tm.h>
354887Schin 
364887Schin #include "lclib.h"
374887Schin 
384887Schin static struct
394887Schin {
404887Schin 	char*		format;
414887Schin 	Lc_info_t*	locale;
424887Schin 	char		null[1];
434887Schin } state;
444887Schin 
454887Schin /*
464887Schin  * this is unix dadgummit
474887Schin  */
484887Schin 
494887Schin static int
504887Schin standardized(Lc_info_t* li, register char** b)
514887Schin {
524887Schin 	if ((li->lc->language->flags & (LC_debug|LC_default)) || streq(li->lc->language->code, "en"))
534887Schin 	{
544887Schin 		b[TM_TIME] = "%H:%M:%S";
554887Schin 		b[TM_DATE] = "%m/%d/%y";
564887Schin 		b[TM_DEFAULT] = "%a %b %e %T %Z %Y";
574887Schin 		return 1;
584887Schin 	}
594887Schin 	return 0;
604887Schin }
614887Schin 
624887Schin /*
634887Schin  * fix up LC_TIME data after loading
644887Schin  */
654887Schin 
664887Schin static void
674887Schin fixup(Lc_info_t* li, register char** b)
684887Schin {
694887Schin 	register char**		v;
704887Schin 	register char**		e;
714887Schin 	register int		n;
724887Schin 
734887Schin 	static int		must[] =
744887Schin 	{
754887Schin 					TM_TIME,
764887Schin 					TM_DATE,
774887Schin 					TM_DEFAULT,
784887Schin 					TM_CTIME,
794887Schin 					TM_DATE_1,
804887Schin 					TM_INTERNATIONAL,
814887Schin 					TM_RECENT,
824887Schin 					TM_DISTANT,
834887Schin 					TM_MERIDIAN_TIME,
844887Schin 	};
854887Schin 
864887Schin 	standardized(li, b);
874887Schin 	for (v = b, e = b + TM_NFORM; v < e; v++)
884887Schin 		if (!*v)
894887Schin 			*v = state.null;
904887Schin 	for (n = 0; n < elementsof(must); n++)
914887Schin 		if (!*b[must[n]])
924887Schin 			b[must[n]] = tm_data.format[must[n]];
934887Schin 	if (li->lc->flags & LC_default)
944887Schin 		for (n = 0; n < TM_NFORM; n++)
954887Schin 			if (!*b[n])
964887Schin 				b[n] = tm_data.format[n];
974887Schin 	if (strchr(b[TM_UT], '%'))
984887Schin 	{
994887Schin 		tm_info.deformat = b[TM_UT];
1004887Schin 		for (n = TM_UT; n < TM_DT; n++)
1014887Schin 			b[n] = state.null;
1024887Schin 	}
1034887Schin 	else
1044887Schin 		tm_info.deformat = b[TM_DEFAULT];
1054887Schin 	tm_info.format = b;
1064887Schin 	if (!(tm_info.deformat = state.format))
1074887Schin 		tm_info.deformat = tm_info.format[TM_DEFAULT];
1084887Schin 	li->data = (void*)b;
1094887Schin }
1104887Schin 
1114887Schin #if _WINIX
1124887Schin 
1134887Schin #include <ast_windows.h>
1144887Schin 
1154887Schin typedef struct Map_s
1164887Schin {
1174887Schin 	LCID		native;
1184887Schin 	int		local;
1194887Schin } Map_t;
1204887Schin 
1214887Schin static const Map_t map[] =
1224887Schin {
1234887Schin 	LOCALE_S1159,			(TM_MERIDIAN+0),
1244887Schin 	LOCALE_S2359,			(TM_MERIDIAN+1),
1254887Schin 	LOCALE_SABBREVDAYNAME1,		(TM_DAY_ABBREV+1),
1264887Schin 	LOCALE_SABBREVDAYNAME2,		(TM_DAY_ABBREV+2),
1274887Schin 	LOCALE_SABBREVDAYNAME3,		(TM_DAY_ABBREV+3),
1284887Schin 	LOCALE_SABBREVDAYNAME4,		(TM_DAY_ABBREV+4),
1294887Schin 	LOCALE_SABBREVDAYNAME5,		(TM_DAY_ABBREV+5),
1304887Schin 	LOCALE_SABBREVDAYNAME6,		(TM_DAY_ABBREV+6),
1314887Schin 	LOCALE_SABBREVDAYNAME7,		(TM_DAY_ABBREV+0),
1324887Schin 	LOCALE_SABBREVMONTHNAME1,	(TM_MONTH_ABBREV+0),
1334887Schin 	LOCALE_SABBREVMONTHNAME2,	(TM_MONTH_ABBREV+1),
1344887Schin 	LOCALE_SABBREVMONTHNAME3,	(TM_MONTH_ABBREV+2),
1354887Schin 	LOCALE_SABBREVMONTHNAME4,	(TM_MONTH_ABBREV+3),
1364887Schin 	LOCALE_SABBREVMONTHNAME5,	(TM_MONTH_ABBREV+4),
1374887Schin 	LOCALE_SABBREVMONTHNAME6,	(TM_MONTH_ABBREV+5),
1384887Schin 	LOCALE_SABBREVMONTHNAME7,	(TM_MONTH_ABBREV+6),
1394887Schin 	LOCALE_SABBREVMONTHNAME8,	(TM_MONTH_ABBREV+7),
1404887Schin 	LOCALE_SABBREVMONTHNAME9,	(TM_MONTH_ABBREV+8),
1414887Schin 	LOCALE_SABBREVMONTHNAME10,	(TM_MONTH_ABBREV+9),
1424887Schin 	LOCALE_SABBREVMONTHNAME11,	(TM_MONTH_ABBREV+10),
1434887Schin 	LOCALE_SABBREVMONTHNAME12,	(TM_MONTH_ABBREV+11),
1444887Schin 	LOCALE_SDAYNAME1,		(TM_DAY+1),
1454887Schin 	LOCALE_SDAYNAME2,		(TM_DAY+2),
1464887Schin 	LOCALE_SDAYNAME3,		(TM_DAY+3),
1474887Schin 	LOCALE_SDAYNAME4,		(TM_DAY+4),
1484887Schin 	LOCALE_SDAYNAME5,		(TM_DAY+5),
1494887Schin 	LOCALE_SDAYNAME6,		(TM_DAY+6),
1504887Schin 	LOCALE_SDAYNAME7,		(TM_DAY+0),
1514887Schin 	LOCALE_SMONTHNAME1,		(TM_MONTH+0),
1524887Schin 	LOCALE_SMONTHNAME2,		(TM_MONTH+1),
1534887Schin 	LOCALE_SMONTHNAME3,		(TM_MONTH+2),
1544887Schin 	LOCALE_SMONTHNAME4,		(TM_MONTH+3),
1554887Schin 	LOCALE_SMONTHNAME5,		(TM_MONTH+4),
1564887Schin 	LOCALE_SMONTHNAME6,		(TM_MONTH+5),
1574887Schin 	LOCALE_SMONTHNAME7,		(TM_MONTH+6),
1584887Schin 	LOCALE_SMONTHNAME8,		(TM_MONTH+7),
1594887Schin 	LOCALE_SMONTHNAME9,		(TM_MONTH+8),
1604887Schin 	LOCALE_SMONTHNAME10,		(TM_MONTH+9),
1614887Schin 	LOCALE_SMONTHNAME11,		(TM_MONTH+10),
1624887Schin 	LOCALE_SMONTHNAME12,		(TM_MONTH+11),
1634887Schin };
1644887Schin 
1654887Schin #undef	extern
1664887Schin 
1674887Schin /*
1684887Schin  * convert ms word date spec w to posix strftime format f
1694887Schin  * next char after f returned
1704887Schin  * the caller already made sure f is big enough
1714887Schin  */
1724887Schin 
1734887Schin static char*
1744887Schin word2posix(register char* f, register char* w, int alternate)
1754887Schin {
1764887Schin 	register char*	r;
1774887Schin 	register int	c;
1784887Schin 	register int	p;
1794887Schin 	register int	n;
1804887Schin 
1814887Schin 	while (*w)
1824887Schin 	{
1834887Schin 		p = 0;
1844887Schin 		r = w;
1854887Schin 		while (*++w == *r);
1864887Schin 		if ((n = w - r) > 3 && alternate)
1874887Schin 			n--;
1884887Schin 		switch (*r)
1894887Schin 		{
1904887Schin 		case 'a':
1914887Schin 		case 'A':
1924887Schin 			if (!strncasecmp(w, "am/pm", 5))
1934887Schin 				w += 5;
1944887Schin 			else if (!strncasecmp(w, "a/p", 3))
1954887Schin 				w += 3;
1964887Schin 			c = 'p';
1974887Schin 			break;
1984887Schin 		case 'd':
1994887Schin 			switch (n)
2004887Schin 			{
2014887Schin 			case 1:
2024887Schin 				p = '-';
2034887Schin 				/*FALLTHROUGH*/
2044887Schin 			case 2:
2054887Schin 				c = 'd';
2064887Schin 				break;
2074887Schin 			case 3:
2084887Schin 				c = 'a';
2094887Schin 				break;
2104887Schin 			default:
2114887Schin 				c = 'A';
2124887Schin 				break;
2134887Schin 			}
2144887Schin 			break;
2154887Schin 		case 'h':
2164887Schin 			switch (n)
2174887Schin 			{
2184887Schin 			case 1:
2194887Schin 				p = '-';
2204887Schin 				/*FALLTHROUGH*/
2214887Schin 			default:
2224887Schin 				c = 'I';
2234887Schin 				break;
2244887Schin 			}
2254887Schin 			break;
2264887Schin 		case 'H':
2274887Schin 			switch (n)
2284887Schin 			{
2294887Schin 			case 1:
2304887Schin 				p = '-';
2314887Schin 				/*FALLTHROUGH*/
2324887Schin 			default:
2334887Schin 				c = 'H';
2344887Schin 				break;
2354887Schin 			}
2364887Schin 			break;
2374887Schin 		case 'M':
2384887Schin 			switch (n)
2394887Schin 			{
2404887Schin 			case 1:
2414887Schin 				p = '-';
2424887Schin 				/*FALLTHROUGH*/
2434887Schin 			case 2:
2444887Schin 				c = 'm';
2454887Schin 				break;
2464887Schin 			case 3:
2474887Schin 				c = 'b';
2484887Schin 				break;
2494887Schin 			default:
2504887Schin 				c = 'B';
2514887Schin 				break;
2524887Schin 			}
2534887Schin 			break;
2544887Schin 		case 'm':
2554887Schin 			switch (n)
2564887Schin 			{
2574887Schin 			case 1:
2584887Schin 				p = '-';
2594887Schin 				/*FALLTHROUGH*/
2604887Schin 			default:
2614887Schin 				c = 'M';
2624887Schin 				break;
2634887Schin 			}
2644887Schin 			break;
2654887Schin 		case 's':
2664887Schin 			switch (n)
2674887Schin 			{
2684887Schin 			case 1:
2694887Schin 				p = '-';
2704887Schin 				/*FALLTHROUGH*/
2714887Schin 			default:
2724887Schin 				c = 'S';
2734887Schin 				break;
2744887Schin 			}
2754887Schin 			break;
2764887Schin 		case 'y':
2774887Schin 			switch (n)
2784887Schin 			{
2794887Schin 			case 1:
2804887Schin 				p = '-';
2814887Schin 				/*FALLTHROUGH*/
2824887Schin 			case 2:
2834887Schin 				c = 'y';
2844887Schin 				break;
2854887Schin 			default:
2864887Schin 				c = 'Y';
2874887Schin 				break;
2884887Schin 			}
2894887Schin 			break;
2904887Schin 		case '\'':
2914887Schin 			if (n & 1)
2924887Schin 				for (w = r + 1; *w; *f++ = *w++)
2934887Schin 					if (*w == '\'')
2944887Schin 					{
2954887Schin 						w++;
2964887Schin 						break;
2974887Schin 					}
2984887Schin 			continue;
2994887Schin 		case '%':
3004887Schin 			while (r < w)
3014887Schin 			{
3024887Schin 				*f++ = *r++;
3034887Schin 				*f++ = *r++;
3044887Schin 			}
3054887Schin 			continue;
3064887Schin 		default:
3074887Schin 			while (r < w)
3084887Schin 				*f++ = *r++;
3094887Schin 			continue;
3104887Schin 		}
3114887Schin 		*f++ = '%';
3124887Schin 		if (p)
3134887Schin 			*f++ = '-';
3144887Schin 		*f++ = c;
3154887Schin 	}
3164887Schin 	*f++ = 0;
3174887Schin 	return f;
3184887Schin }
3194887Schin 
3204887Schin /*
3214887Schin  * load the native LC_TIME data for the current locale
3224887Schin  */
3234887Schin 
3244887Schin static void
3254887Schin native_lc_time(Lc_info_t* li)
3264887Schin {
3274887Schin 	register char*	s;
3284887Schin 	register char*	t;
3294887Schin 	register char**	b;
3304887Schin 	register int	n;
3314887Schin 	register int	m;
3324887Schin 	register int	i;
3334887Schin 	LCID		lcid;
3344887Schin 	int		nt;
3354887Schin 	int		ns;
3364887Schin 	int		nl;
3374887Schin 	int		clock_24;
3384887Schin 	int		leading_0;
3394887Schin 	char		buf[256];
3404887Schin 
3414887Schin 	lcid = li->lc->index;
3424887Schin 	nt = 2 * GetLocaleInfo(lcid, LOCALE_STIME, 0, 0) + 7; /* HH:MM:SS */
3434887Schin 	ns = 3 * GetLocaleInfo(lcid, LOCALE_SSHORTDATE, 0, 0);
3444887Schin 	nl = 3 * GetLocaleInfo(lcid, LOCALE_SLONGDATE, 0, 0);
3454887Schin 	n = nt + ns + nl;
3464887Schin 	for (i = 0; i < elementsof(map); i++)
3474887Schin 		n += GetLocaleInfo(lcid, map[i].native, 0, 0);
3484887Schin 	if (!(b = newof(0, char*, TM_NFORM, n)))
3494887Schin 		return;
3504887Schin 	s = (char*)(b + TM_NFORM);
3514887Schin 	for (i = 0; i < elementsof(map); i++)
3524887Schin 	{
3534887Schin 		if (!(m = GetLocaleInfo(lcid, map[i].native, s, n)))
3544887Schin 			goto bad;
3554887Schin 		b[map[i].local] = s;
3564887Schin 		s += m;
3574887Schin 	}
3584887Schin 	if (!standardized(li, b))
3594887Schin 	{
3604887Schin 		/*
3614887Schin 		 * synthesize TM_TIME format from the ms word template
3624887Schin 		 */
3634887Schin 
3644887Schin 		if (!GetLocaleInfo(lcid, LOCALE_ITIME, buf, sizeof(buf)))
3654887Schin 			goto bad;
3664887Schin 		clock_24 = atoi(buf);
3674887Schin 		if (!GetLocaleInfo(lcid, LOCALE_ITLZERO, buf, sizeof(buf)))
3684887Schin 			goto bad;
3694887Schin 		leading_0 = atoi(buf);
3704887Schin 		if (!GetLocaleInfo(lcid, LOCALE_STIME, buf, sizeof(buf)))
3714887Schin 			goto bad;
3724887Schin 		b[TM_TIME] = s;
3734887Schin 		*s++ = '%';
3744887Schin 		if (!leading_0)
3754887Schin 			*s++ = '-';
3764887Schin 		*s++ = clock_24 ? 'H' : 'I';
3774887Schin 		for (t = buf; *s = *t++; s++);
3784887Schin 		*s++ = '%';
3794887Schin 		if (!leading_0)
3804887Schin 			*s++ = '-';
3814887Schin 		*s++ = 'M';
3824887Schin 		for (t = buf; *s = *t++; s++);
3834887Schin 		*s++ = '%';
3844887Schin 		if (!leading_0)
3854887Schin 			*s++ = '-';
3864887Schin 		*s++ = 'S';
3874887Schin 		*s++ = 0;
3884887Schin 
3894887Schin 		/*
3904887Schin 		 * synthesize TM_DATE format
3914887Schin 		 */
3924887Schin 
3934887Schin 		if (!GetLocaleInfo(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)))
3944887Schin 			goto bad;
3954887Schin 		b[TM_DATE] = s;
3964887Schin 		s = word2posix(s, buf, 1);
3974887Schin 
3984887Schin 		/*
3994887Schin 		 * synthesize TM_DEFAULT format
4004887Schin 		 */
4014887Schin 
4024887Schin 		if (!GetLocaleInfo(lcid, LOCALE_SLONGDATE, buf, sizeof(buf)))
4034887Schin 			goto bad;
4044887Schin 		b[TM_DEFAULT] = s;
4054887Schin 		s = word2posix(s, buf, 1);
4064887Schin 		strcpy(s - 1, " %X");
4074887Schin 	}
4084887Schin 
4094887Schin 	/*
4104887Schin 	 * done
4114887Schin 	 */
4124887Schin 
4134887Schin 	fixup(li, b);
4144887Schin 	return;
4154887Schin  bad:
4164887Schin 	free(b);
4174887Schin }
4184887Schin 
4194887Schin #else
4204887Schin 
4214887Schin #if _lib_nl_langinfo && _hdr_langinfo
4224887Schin 
4234887Schin #if _hdr_nl_types
4244887Schin #include <nl_types.h>
4254887Schin #endif
4264887Schin 
4274887Schin #include <langinfo.h>
4284887Schin 
4294887Schin typedef struct Map_s
4304887Schin {
4314887Schin 	int		native;
4324887Schin 	int		local;
4334887Schin } Map_t;
4344887Schin 
4354887Schin static const Map_t map[] =
4364887Schin {
4374887Schin 	AM_STR,				(TM_MERIDIAN+0),
4384887Schin 	PM_STR,				(TM_MERIDIAN+1),
4394887Schin 	ABDAY_1,			(TM_DAY_ABBREV+0),
4404887Schin 	ABDAY_2,			(TM_DAY_ABBREV+1),
4414887Schin 	ABDAY_3,			(TM_DAY_ABBREV+2),
4424887Schin 	ABDAY_4,			(TM_DAY_ABBREV+3),
4434887Schin 	ABDAY_5,			(TM_DAY_ABBREV+4),
4444887Schin 	ABDAY_6,			(TM_DAY_ABBREV+5),
4454887Schin 	ABDAY_7,			(TM_DAY_ABBREV+6),
4464887Schin 	ABMON_1,			(TM_MONTH_ABBREV+0),
4474887Schin 	ABMON_2,			(TM_MONTH_ABBREV+1),
4484887Schin 	ABMON_3,			(TM_MONTH_ABBREV+2),
4494887Schin 	ABMON_4,			(TM_MONTH_ABBREV+3),
4504887Schin 	ABMON_5,			(TM_MONTH_ABBREV+4),
4514887Schin 	ABMON_6,			(TM_MONTH_ABBREV+5),
4524887Schin 	ABMON_7,			(TM_MONTH_ABBREV+6),
4534887Schin 	ABMON_8,			(TM_MONTH_ABBREV+7),
4544887Schin 	ABMON_9,			(TM_MONTH_ABBREV+8),
4554887Schin 	ABMON_10,			(TM_MONTH_ABBREV+9),
4564887Schin 	ABMON_11,			(TM_MONTH_ABBREV+10),
4574887Schin 	ABMON_12,			(TM_MONTH_ABBREV+11),
4584887Schin 	DAY_1,				(TM_DAY+0),
4594887Schin 	DAY_2,				(TM_DAY+1),
4604887Schin 	DAY_3,				(TM_DAY+2),
4614887Schin 	DAY_4,				(TM_DAY+3),
4624887Schin 	DAY_5,				(TM_DAY+4),
4634887Schin 	DAY_6,				(TM_DAY+5),
4644887Schin 	DAY_7,				(TM_DAY+6),
4654887Schin 	MON_1,				(TM_MONTH+0),
4664887Schin 	MON_2,				(TM_MONTH+1),
4674887Schin 	MON_3,				(TM_MONTH+2),
4684887Schin 	MON_4,				(TM_MONTH+3),
4694887Schin 	MON_5,				(TM_MONTH+4),
4704887Schin 	MON_6,				(TM_MONTH+5),
4714887Schin 	MON_7,				(TM_MONTH+6),
4724887Schin 	MON_8,				(TM_MONTH+7),
4734887Schin 	MON_9,				(TM_MONTH+8),
4744887Schin 	MON_10,				(TM_MONTH+9),
4754887Schin 	MON_11,				(TM_MONTH+10),
4764887Schin 	MON_12,				(TM_MONTH+11),
477*8462SApril.Chin@Sun.COM #ifdef _DATE_FMT
478*8462SApril.Chin@Sun.COM 	_DATE_FMT,			TM_DEFAULT,
479*8462SApril.Chin@Sun.COM #else
4804887Schin 	D_T_FMT,			TM_DEFAULT,
481*8462SApril.Chin@Sun.COM #endif
4824887Schin 	D_FMT,				TM_DATE,
4834887Schin 	T_FMT,				TM_TIME,
4844887Schin #ifdef ERA
4854887Schin 	ERA,				TM_ERA,
4864887Schin 	ERA_D_T_FMT,			TM_ERA_DEFAULT,
4874887Schin 	ERA_D_FMT,			TM_ERA_DATE,
4884887Schin 	ERA_T_FMT,			TM_ERA_TIME,
4894887Schin #endif
4904887Schin #ifdef ALT_DIGITS
4914887Schin 	ALT_DIGITS,			TM_DIGITS,
4924887Schin #endif
4934887Schin };
4944887Schin 
4954887Schin static void
4964887Schin native_lc_time(Lc_info_t* li)
4974887Schin {
4984887Schin 	register char*	s;
4994887Schin 	register char*	t;
5004887Schin 	register char**	b;
5014887Schin 	register int	n;
5024887Schin 	register int	m;
5034887Schin 	register int	i;
5044887Schin 
5054887Schin 	n = 0;
5064887Schin 	for (i = 0; i < elementsof(map); i++)
5074887Schin 		n += strlen(nl_langinfo(map[i].native)) + 1;
5084887Schin 	if (!(b = newof(0, char*, TM_NFORM, n)))
5094887Schin 		return;
5104887Schin 	s = (char*)(b + TM_NFORM);
5114887Schin 	for (i = 0; i < elementsof(map); i++)
5124887Schin 	{
5134887Schin 		b[map[i].local] = s;
5144887Schin 		t = nl_langinfo(map[i].native);
5154887Schin 		while (*s++ = *t++);
5164887Schin 	}
5174887Schin 	fixup(li, b);
5184887Schin }
5194887Schin 
5204887Schin #else
5214887Schin 
5224887Schin #define native_lc_time(li)	((li->data=(void*)(tm_info.format=tm_data.format)),(tm_info.deformat=tm_info.format[TM_DEFAULT]))
5234887Schin 
5244887Schin #endif
5254887Schin 
5264887Schin #endif
5274887Schin 
5284887Schin /*
5294887Schin  * load the LC_TIME data for the current locale
5304887Schin  */
5314887Schin 
5324887Schin static void
5334887Schin load(Lc_info_t* li)
5344887Schin {
5354887Schin 	register char*		s;
5364887Schin 	register char**		b;
5374887Schin 	register char**		v;
5384887Schin 	register char**		e;
5394887Schin 	unsigned char*		u;
5404887Schin 	ssize_t			n;
5414887Schin 	iconv_t			cvt;
5424887Schin 	Sfio_t*			sp;
5434887Schin 	Sfio_t*			tp;
5444887Schin 	char			path[PATH_MAX];
5454887Schin 
5464887Schin 	if (b = (char**)li->data)
5474887Schin 	{
5484887Schin 		tm_info.format = b;
5494887Schin 		if (!(tm_info.deformat = state.format))
5504887Schin 			tm_info.deformat = tm_info.format[TM_DEFAULT];
5514887Schin 		return;
5524887Schin 	}
5534887Schin 	tm_info.format = tm_data.format;
5544887Schin 	if (!(tm_info.deformat = state.format))
5554887Schin 		tm_info.deformat = tm_info.format[TM_DEFAULT];
5564887Schin 	if (mcfind(path, NiL, NiL, LC_TIME, 0) && (sp = sfopen(NiL, path, "r")))
5574887Schin 	{
5584887Schin 		n = sfsize(sp);
5594887Schin 		tp = 0;
5604887Schin 		if (u = (unsigned char*)sfreserve(sp, 3, 1))
5614887Schin 		{
5624887Schin 			if (u[0] == 0xef && u[1] == 0xbb && u[2] == 0xbf && (cvt = iconv_open("", "utf")) != (iconv_t)(-1))
5634887Schin 			{
5644887Schin 				if (tp = sfstropen())
5654887Schin 				{
5664887Schin 					sfread(sp, u, 3);
5674887Schin 					n = iconv_move(cvt, sp, tp, SF_UNBOUND, NiL);
5684887Schin 				}
5694887Schin 				iconv_close(cvt);
5704887Schin 			}
5714887Schin 			if (!tp)
5724887Schin 				sfread(sp, u, 0);
5734887Schin 		}
5744887Schin 		if (b = newof(0, char*, TM_NFORM, n + 2))
5754887Schin 		{
5764887Schin 			v = b;
5774887Schin 			e = b + TM_NFORM;
5784887Schin 			s = (char*)e;
5794887Schin 			if (tp && memcpy(s, sfstrbase(tp), n) || !tp && sfread(sp, s, n) == n)
5804887Schin 			{
5814887Schin 				s[n] = '\n';
5824887Schin 				while (v < e)
5834887Schin 				{
5844887Schin 					*v++ = s;
5854887Schin 					if (!(s = strchr(s, '\n')))
5864887Schin 						break;
5874887Schin 					*s++ = 0;
5884887Schin 				}
5894887Schin 				fixup(li, b);
5904887Schin 			}
5914887Schin 			else
5924887Schin 				free(b);
5934887Schin 		}
5944887Schin 		if (tp)
5954887Schin 			sfclose(tp);
5964887Schin 		sfclose(sp);
5974887Schin 	}
5984887Schin 	else
5994887Schin 		native_lc_time(li);
6004887Schin }
6014887Schin 
6024887Schin /*
6034887Schin  * check that tm_info.format matches the current locale
6044887Schin  */
6054887Schin 
6064887Schin char**
6074887Schin tmlocale(void)
6084887Schin {
6094887Schin 	Lc_info_t*	li;
6104887Schin 
6114887Schin 	if (!tm_info.format)
6124887Schin 	{
6134887Schin 		tm_info.format = tm_data.format;
6144887Schin 		if (!tm_info.deformat)
6154887Schin 			tm_info.deformat = tm_info.format[TM_DEFAULT];
6164887Schin 		else if (tm_info.deformat != tm_info.format[TM_DEFAULT])
6174887Schin 			state.format = tm_info.deformat;
6184887Schin 	}
6194887Schin 	li = LCINFO(AST_LC_TIME);
6204887Schin 	if (!li->data)
6214887Schin 		load(li);
6224887Schin 	return tm_info.format;
6234887Schin }
624