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