3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering/***********************************************************************
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* This software is part of the ast package *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Copyright (c) 1985-2011 AT&T Intellectual Property *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* and is licensed under the *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Eclipse Public License, Version 1.0 *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* by AT&T Intellectual Property *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* A copy of the License is available at *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* http://www.eclipse.org/org/documents/epl-v10.html *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Information and Software Systems Research *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* AT&T Research *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Florham Park NJ *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Glenn Fowler <gsf@research.att.com> *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* David Korn <dgk@research.att.com> *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* Phong Vo <kpv@research.att.com> *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering* *
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering***********************************************************************/
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog#pragma prototyped
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering/*
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell * Glenn Fowler
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering * AT&T Research
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering *
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering * time conversion translation support
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog */
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include <ast.h>
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include <cdt.h>
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include <iconv.h>
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include <mc.h>
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include <tm.h>
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering#include <ast_nl_types.h>
288a74cce597f81d3ba01d8a5ca7d2ba5b654b7eRonny Chevalier
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering#include "lclib.h"
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskogstatic struct
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog{
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog char* format;
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog Lc_info_t* locale;
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog char null[1];
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog} state;
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog/*
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog * this is unix dadgummit
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog */
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskogstatic int
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskogstandardized(Lc_info_t* li, register char** b)
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog{
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering if ((li->lc->language->flags & (LC_debug|LC_default)) || streq(li->lc->language->code, "en"))
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering {
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering b[TM_TIME] = "%H:%M:%S";
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering b[TM_DATE] = "%m/%d/%y";
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering b[TM_DEFAULT] = "%a %b %e %T %Z %Y";
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering return 1;
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering }
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog return 0;
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog}
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek/*
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering * fix up LC_TIME data after loading
fb4729006a7174472e8a435b0887e532cd6217fcZbigniew Jędrzejewski-Szmek */
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poetteringstatic void
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poetteringfixup(Lc_info_t* li, register char** b)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering{
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering register char** v;
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering register char** e;
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering register int n;
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog static int must[] =
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog {
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog TM_TIME,
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek TM_DATE,
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek TM_DEFAULT,
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek TM_MERIDIAN,
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog TM_UT,
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog TM_DT,
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog TM_SUFFIXES,
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog TM_PARTS,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_HOURS,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_DAYS,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_LAST,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_THIS,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_NEXT,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_EXACT,
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek TM_NOISE,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_ORDINAL,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_CTIME,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_DATE_1,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_INTERNATIONAL,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_RECENT,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_DISTANT,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_MERIDIAN_TIME,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_ORDINALS,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_FINAL,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering TM_WORK,
ad79565d6b37bcc93cf773a39b975e5b85d122daUmut Tezduyar Lindskog };
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering standardized(li, b);
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering for (v = b, e = b + TM_NFORM; v < e; v++)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering if (!*v)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering *v = state.null;
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering for (n = 0; n < elementsof(must); n++)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering if (!*b[must[n]])
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt b[must[n]] = tm_data.format[must[n]];
fb4729006a7174472e8a435b0887e532cd6217fcZbigniew Jędrzejewski-Szmek if (li->lc->flags & LC_default)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering for (n = 0; n < TM_NFORM; n++)
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering if (!*b[n])
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering b[n] = tm_data.format[n];
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (strchr(b[TM_UT], '%'))
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering {
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering tm_info.deformat = b[TM_UT];
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering for (n = TM_UT; n < TM_DT; n++)
b[n] = state.null;
}
else
tm_info.deformat = b[TM_DEFAULT];
tm_info.format = b;
if (!(tm_info.deformat = state.format))
tm_info.deformat = tm_info.format[TM_DEFAULT];
li->data = (void*)b;
}
#if _WINIX
#include <ast_windows.h>
typedef struct Map_s
{
LCID native;
int local;
} Map_t;
static const Map_t map[] =
{
LOCALE_S1159, (TM_MERIDIAN+0),
LOCALE_S2359, (TM_MERIDIAN+1),
LOCALE_SABBREVDAYNAME1, (TM_DAY_ABBREV+1),
LOCALE_SABBREVDAYNAME2, (TM_DAY_ABBREV+2),
LOCALE_SABBREVDAYNAME3, (TM_DAY_ABBREV+3),
LOCALE_SABBREVDAYNAME4, (TM_DAY_ABBREV+4),
LOCALE_SABBREVDAYNAME5, (TM_DAY_ABBREV+5),
LOCALE_SABBREVDAYNAME6, (TM_DAY_ABBREV+6),
LOCALE_SABBREVDAYNAME7, (TM_DAY_ABBREV+0),
LOCALE_SABBREVMONTHNAME1, (TM_MONTH_ABBREV+0),
LOCALE_SABBREVMONTHNAME2, (TM_MONTH_ABBREV+1),
LOCALE_SABBREVMONTHNAME3, (TM_MONTH_ABBREV+2),
LOCALE_SABBREVMONTHNAME4, (TM_MONTH_ABBREV+3),
LOCALE_SABBREVMONTHNAME5, (TM_MONTH_ABBREV+4),
LOCALE_SABBREVMONTHNAME6, (TM_MONTH_ABBREV+5),
LOCALE_SABBREVMONTHNAME7, (TM_MONTH_ABBREV+6),
LOCALE_SABBREVMONTHNAME8, (TM_MONTH_ABBREV+7),
LOCALE_SABBREVMONTHNAME9, (TM_MONTH_ABBREV+8),
LOCALE_SABBREVMONTHNAME10, (TM_MONTH_ABBREV+9),
LOCALE_SABBREVMONTHNAME11, (TM_MONTH_ABBREV+10),
LOCALE_SABBREVMONTHNAME12, (TM_MONTH_ABBREV+11),
LOCALE_SDAYNAME1, (TM_DAY+1),
LOCALE_SDAYNAME2, (TM_DAY+2),
LOCALE_SDAYNAME3, (TM_DAY+3),
LOCALE_SDAYNAME4, (TM_DAY+4),
LOCALE_SDAYNAME5, (TM_DAY+5),
LOCALE_SDAYNAME6, (TM_DAY+6),
LOCALE_SDAYNAME7, (TM_DAY+0),
LOCALE_SMONTHNAME1, (TM_MONTH+0),
LOCALE_SMONTHNAME2, (TM_MONTH+1),
LOCALE_SMONTHNAME3, (TM_MONTH+2),
LOCALE_SMONTHNAME4, (TM_MONTH+3),
LOCALE_SMONTHNAME5, (TM_MONTH+4),
LOCALE_SMONTHNAME6, (TM_MONTH+5),
LOCALE_SMONTHNAME7, (TM_MONTH+6),
LOCALE_SMONTHNAME8, (TM_MONTH+7),
LOCALE_SMONTHNAME9, (TM_MONTH+8),
LOCALE_SMONTHNAME10, (TM_MONTH+9),
LOCALE_SMONTHNAME11, (TM_MONTH+10),
LOCALE_SMONTHNAME12, (TM_MONTH+11),
};
#undef extern
/*
* convert ms word date spec w to posix strftime format f
* next char after f returned
* the caller already made sure f is big enough
*/
static char*
word2posix(register char* f, register char* w, int alternate)
{
register char* r;
register int c;
register int p;
register int n;
while (*w)
{
p = 0;
r = w;
while (*++w == *r);
if ((n = w - r) > 3 && alternate)
n--;
switch (*r)
{
case 'a':
case 'A':
if (!strncasecmp(w, "am/pm", 5))
w += 5;
else if (!strncasecmp(w, "a/p", 3))
w += 3;
c = 'p';
break;
case 'd':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
case 2:
c = 'd';
break;
case 3:
c = 'a';
break;
default:
c = 'A';
break;
}
break;
case 'h':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
default:
c = 'I';
break;
}
break;
case 'H':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
default:
c = 'H';
break;
}
break;
case 'M':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
case 2:
c = 'm';
break;
case 3:
c = 'b';
break;
default:
c = 'B';
break;
}
break;
case 'm':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
default:
c = 'M';
break;
}
break;
case 's':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
default:
c = 'S';
break;
}
break;
case 'y':
switch (n)
{
case 1:
p = '-';
/*FALLTHROUGH*/
case 2:
c = 'y';
break;
default:
c = 'Y';
break;
}
break;
case '\'':
if (n & 1)
for (w = r + 1; *w; *f++ = *w++)
if (*w == '\'')
{
w++;
break;
}
continue;
case '%':
while (r < w)
{
*f++ = *r++;
*f++ = *r++;
}
continue;
default:
while (r < w)
*f++ = *r++;
continue;
}
*f++ = '%';
if (p)
*f++ = '-';
*f++ = c;
}
*f++ = 0;
return f;
}
/*
* load the native LC_TIME data for the current locale
*/
static void
native_lc_time(Lc_info_t* li)
{
register char* s;
register char* t;
register char** b;
register int n;
register int m;
register int i;
LCID lcid;
int nt;
int ns;
int nl;
int clock_24;
int leading_0;
char buf[256];
lcid = li->lc->index;
nt = 2 * GetLocaleInfo(lcid, LOCALE_STIME, 0, 0) + 7; /* HH:MM:SS */
ns = 3 * GetLocaleInfo(lcid, LOCALE_SSHORTDATE, 0, 0);
nl = 3 * GetLocaleInfo(lcid, LOCALE_SLONGDATE, 0, 0);
n = nt + ns + nl;
for (i = 0; i < elementsof(map); i++)
n += GetLocaleInfo(lcid, map[i].native, 0, 0);
if (!(b = newof(0, char*, TM_NFORM, n)))
return;
s = (char*)(b + TM_NFORM);
for (i = 0; i < elementsof(map); i++)
{
if (!(m = GetLocaleInfo(lcid, map[i].native, s, n)))
goto bad;
b[map[i].local] = s;
s += m;
}
if (!standardized(li, b))
{
/*
* synthesize TM_TIME format from the ms word template
*/
if (!GetLocaleInfo(lcid, LOCALE_ITIME, buf, sizeof(buf)))
goto bad;
clock_24 = atoi(buf);
if (!GetLocaleInfo(lcid, LOCALE_ITLZERO, buf, sizeof(buf)))
goto bad;
leading_0 = atoi(buf);
if (!GetLocaleInfo(lcid, LOCALE_STIME, buf, sizeof(buf)))
goto bad;
b[TM_TIME] = s;
*s++ = '%';
if (!leading_0)
*s++ = '-';
*s++ = clock_24 ? 'H' : 'I';
for (t = buf; *s = *t++; s++);
*s++ = '%';
if (!leading_0)
*s++ = '-';
*s++ = 'M';
for (t = buf; *s = *t++; s++);
*s++ = '%';
if (!leading_0)
*s++ = '-';
*s++ = 'S';
*s++ = 0;
/*
* synthesize TM_DATE format
*/
if (!GetLocaleInfo(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)))
goto bad;
b[TM_DATE] = s;
s = word2posix(s, buf, 1);
/*
* synthesize TM_DEFAULT format
*/
if (!GetLocaleInfo(lcid, LOCALE_SLONGDATE, buf, sizeof(buf)))
goto bad;
b[TM_DEFAULT] = s;
s = word2posix(s, buf, 1);
strcpy(s - 1, " %X");
}
/*
* done
*/
fixup(li, b);
return;
bad:
free(b);
}
#else
#if _lib_nl_langinfo && _hdr_langinfo
#if _hdr_nl_types
#include <nl_types.h>
#endif
#include <langinfo.h>
typedef struct Map_s
{
int native;
int local;
} Map_t;
static const Map_t map[] =
{
AM_STR, (TM_MERIDIAN+0),
PM_STR, (TM_MERIDIAN+1),
ABDAY_1, (TM_DAY_ABBREV+0),
ABDAY_2, (TM_DAY_ABBREV+1),
ABDAY_3, (TM_DAY_ABBREV+2),
ABDAY_4, (TM_DAY_ABBREV+3),
ABDAY_5, (TM_DAY_ABBREV+4),
ABDAY_6, (TM_DAY_ABBREV+5),
ABDAY_7, (TM_DAY_ABBREV+6),
ABMON_1, (TM_MONTH_ABBREV+0),
ABMON_2, (TM_MONTH_ABBREV+1),
ABMON_3, (TM_MONTH_ABBREV+2),
ABMON_4, (TM_MONTH_ABBREV+3),
ABMON_5, (TM_MONTH_ABBREV+4),
ABMON_6, (TM_MONTH_ABBREV+5),
ABMON_7, (TM_MONTH_ABBREV+6),
ABMON_8, (TM_MONTH_ABBREV+7),
ABMON_9, (TM_MONTH_ABBREV+8),
ABMON_10, (TM_MONTH_ABBREV+9),
ABMON_11, (TM_MONTH_ABBREV+10),
ABMON_12, (TM_MONTH_ABBREV+11),
DAY_1, (TM_DAY+0),
DAY_2, (TM_DAY+1),
DAY_3, (TM_DAY+2),
DAY_4, (TM_DAY+3),
DAY_5, (TM_DAY+4),
DAY_6, (TM_DAY+5),
DAY_7, (TM_DAY+6),
MON_1, (TM_MONTH+0),
MON_2, (TM_MONTH+1),
MON_3, (TM_MONTH+2),
MON_4, (TM_MONTH+3),
MON_5, (TM_MONTH+4),
MON_6, (TM_MONTH+5),
MON_7, (TM_MONTH+6),
MON_8, (TM_MONTH+7),
MON_9, (TM_MONTH+8),
MON_10, (TM_MONTH+9),
MON_11, (TM_MONTH+10),
MON_12, (TM_MONTH+11),
#ifdef _DATE_FMT
_DATE_FMT, TM_DEFAULT,
#else
D_T_FMT, TM_DEFAULT,
#endif
D_FMT, TM_DATE,
T_FMT, TM_TIME,
#ifdef ERA
ERA, TM_ERA,
ERA_D_T_FMT, TM_ERA_DEFAULT,
ERA_D_FMT, TM_ERA_DATE,
ERA_T_FMT, TM_ERA_TIME,
#endif
#ifdef ALT_DIGITS
ALT_DIGITS, TM_DIGITS,
#endif
};
static void
native_lc_time(Lc_info_t* li)
{
register char* s;
register char* t;
register char** b;
register int n;
register int i;
n = 0;
for (i = 0; i < elementsof(map); i++)
{
if (!(t = nl_langinfo(map[i].native)))
t = tm_data.format[map[i].local];
n += strlen(t) + 1;
}
if (!(b = newof(0, char*, TM_NFORM, n)))
return;
s = (char*)(b + TM_NFORM);
for (i = 0; i < elementsof(map); i++)
{
b[map[i].local] = s;
if (!(t = nl_langinfo(map[i].native)))
t = tm_data.format[map[i].local];
while (*s++ = *t++);
}
fixup(li, b);
}
#else
#define native_lc_time(li) ((li->data=(void*)(tm_info.format=tm_data.format)),(tm_info.deformat=tm_info.format[TM_DEFAULT]))
#endif
#endif
/*
* load the LC_TIME data for the current locale
*/
static void
load(Lc_info_t* li)
{
register char* s;
register char** b;
register char** v;
register char** e;
unsigned char* u;
ssize_t n;
iconv_t cvt;
Sfio_t* sp;
Sfio_t* tp;
char path[PATH_MAX];
if (b = (char**)li->data)
{
tm_info.format = b;
if (!(tm_info.deformat = state.format))
tm_info.deformat = tm_info.format[TM_DEFAULT];
return;
}
tm_info.format = tm_data.format;
if (!(tm_info.deformat = state.format))
tm_info.deformat = tm_info.format[TM_DEFAULT];
if (mcfind(NiL, NiL, LC_TIME, 0, path, sizeof(path)) && (sp = sfopen(NiL, path, "r")))
{
n = sfsize(sp);
tp = 0;
if (u = (unsigned char*)sfreserve(sp, 3, 1))
{
if (u[0] == 0xef && u[1] == 0xbb && u[2] == 0xbf && (cvt = iconv_open("", "utf")) != (iconv_t)(-1))
{
if (tp = sfstropen())
{
sfread(sp, u, 3);
n = iconv_move(cvt, sp, tp, SF_UNBOUND, NiL);
}
iconv_close(cvt);
}
if (!tp)
sfread(sp, u, 0);
}
if (b = newof(0, char*, TM_NFORM, n + 2))
{
v = b;
e = b + TM_NFORM;
s = (char*)e;
if (tp && memcpy(s, sfstrbase(tp), n) || !tp && sfread(sp, s, n) == n)
{
s[n] = '\n';
while (v < e)
{
*v++ = s;
if (!(s = strchr(s, '\n')))
break;
*s++ = 0;
}
fixup(li, b);
}
else
free(b);
}
if (tp)
sfclose(tp);
sfclose(sp);
}
else
native_lc_time(li);
}
/*
* check that tm_info.format matches the current locale
*/
char**
tmlocale(void)
{
Lc_info_t* li;
if (!tm_info.format)
{
tm_info.format = tm_data.format;
if (!tm_info.deformat)
tm_info.deformat = tm_info.format[TM_DEFAULT];
else if (tm_info.deformat != tm_info.format[TM_DEFAULT])
state.format = tm_info.deformat;
}
li = LCINFO(AST_LC_TIME);
if (!li->data)
load(li);
return tm_info.format;
}