16b5e5868SGarrett D'Amore /* 26b5e5868SGarrett D'Amore * This file and its contents are supplied under the terms of the 36b5e5868SGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 45aec55ebSGarrett D'Amore * You may only use this file in accordance with the terms of version 55aec55ebSGarrett D'Amore * 1.0 of the CDDL. 66b5e5868SGarrett D'Amore * 76b5e5868SGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 86b5e5868SGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 96b5e5868SGarrett D'Amore * http://www.illumos.org/license/CDDL. 106b5e5868SGarrett D'Amore */ 116b5e5868SGarrett D'Amore 126b5e5868SGarrett D'Amore /* 13*2d08521bSGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org> 146b5e5868SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 156b5e5868SGarrett D'Amore */ 166b5e5868SGarrett D'Amore 176b5e5868SGarrett D'Amore /* 186b5e5868SGarrett D'Amore * LC_TIME database generation routines for localedef. 196b5e5868SGarrett D'Amore */ 206b5e5868SGarrett D'Amore 216b5e5868SGarrett D'Amore #include <stdio.h> 226b5e5868SGarrett D'Amore #include <stdlib.h> 236b5e5868SGarrett D'Amore #include <errno.h> 246b5e5868SGarrett D'Amore #include <sys/types.h> 256b5e5868SGarrett D'Amore #include <string.h> 266b5e5868SGarrett D'Amore #include <unistd.h> 276b5e5868SGarrett D'Amore #include "localedef.h" 286b5e5868SGarrett D'Amore #include "parser.tab.h" 296b5e5868SGarrett D'Amore #include "timelocal.h" 306b5e5868SGarrett D'Amore 31*2d08521bSGarrett D'Amore struct lc_time tm; 326b5e5868SGarrett D'Amore 336b5e5868SGarrett D'Amore void 346b5e5868SGarrett D'Amore init_time(void) 356b5e5868SGarrett D'Amore { 366b5e5868SGarrett D'Amore (void) memset(&tm, 0, sizeof (tm)); 376b5e5868SGarrett D'Amore } 386b5e5868SGarrett D'Amore 396b5e5868SGarrett D'Amore void 406b5e5868SGarrett D'Amore add_time_str(wchar_t *wcs) 416b5e5868SGarrett D'Amore { 426b5e5868SGarrett D'Amore char *str; 436b5e5868SGarrett D'Amore 446b5e5868SGarrett D'Amore if ((str = to_mb_string(wcs)) == NULL) { 456b5e5868SGarrett D'Amore INTERR; 466b5e5868SGarrett D'Amore return; 476b5e5868SGarrett D'Amore } 486b5e5868SGarrett D'Amore free(wcs); 496b5e5868SGarrett D'Amore 506b5e5868SGarrett D'Amore switch (last_kw) { 516b5e5868SGarrett D'Amore case T_D_T_FMT: 526b5e5868SGarrett D'Amore tm.c_fmt = str; 536b5e5868SGarrett D'Amore break; 546b5e5868SGarrett D'Amore case T_D_FMT: 556b5e5868SGarrett D'Amore tm.x_fmt = str; 566b5e5868SGarrett D'Amore break; 576b5e5868SGarrett D'Amore case T_T_FMT: 586b5e5868SGarrett D'Amore tm.X_fmt = str; 596b5e5868SGarrett D'Amore break; 606b5e5868SGarrett D'Amore case T_T_FMT_AMPM: 616b5e5868SGarrett D'Amore tm.ampm_fmt = str; 626b5e5868SGarrett D'Amore break; 636b5e5868SGarrett D'Amore case T_DATE_FMT: 646b5e5868SGarrett D'Amore /* 656b5e5868SGarrett D'Amore * This one is a Solaris extension, Too bad date just 666b5e5868SGarrett D'Amore * doesn't use %c, which would be simpler. 676b5e5868SGarrett D'Amore */ 686b5e5868SGarrett D'Amore tm.date_fmt = str; 696b5e5868SGarrett D'Amore break; 706b5e5868SGarrett D'Amore case T_ERA_D_FMT: 716b5e5868SGarrett D'Amore case T_ERA_T_FMT: 726b5e5868SGarrett D'Amore case T_ERA_D_T_FMT: 736b5e5868SGarrett D'Amore /* Silently ignore it. */ 746b5e5868SGarrett D'Amore break; 756b5e5868SGarrett D'Amore default: 766b5e5868SGarrett D'Amore free(str); 776b5e5868SGarrett D'Amore INTERR; 786b5e5868SGarrett D'Amore break; 796b5e5868SGarrett D'Amore } 806b5e5868SGarrett D'Amore } 816b5e5868SGarrett D'Amore 826b5e5868SGarrett D'Amore static void 836b5e5868SGarrett D'Amore add_list(const char *ptr[], char *str, int limit) 846b5e5868SGarrett D'Amore { 856b5e5868SGarrett D'Amore int i; 866b5e5868SGarrett D'Amore for (i = 0; i < limit; i++) { 876b5e5868SGarrett D'Amore if (ptr[i] == NULL) { 886b5e5868SGarrett D'Amore ptr[i] = str; 896b5e5868SGarrett D'Amore return; 906b5e5868SGarrett D'Amore } 916b5e5868SGarrett D'Amore } 926b5e5868SGarrett D'Amore errf(_("too many list elements")); 936b5e5868SGarrett D'Amore } 946b5e5868SGarrett D'Amore 956b5e5868SGarrett D'Amore void 966b5e5868SGarrett D'Amore add_time_list(wchar_t *wcs) 976b5e5868SGarrett D'Amore { 986b5e5868SGarrett D'Amore char *str; 996b5e5868SGarrett D'Amore 1006b5e5868SGarrett D'Amore if ((str = to_mb_string(wcs)) == NULL) { 1016b5e5868SGarrett D'Amore INTERR; 1026b5e5868SGarrett D'Amore return; 1036b5e5868SGarrett D'Amore } 1046b5e5868SGarrett D'Amore free(wcs); 1056b5e5868SGarrett D'Amore 1066b5e5868SGarrett D'Amore switch (last_kw) { 1076b5e5868SGarrett D'Amore case T_ABMON: 1086b5e5868SGarrett D'Amore add_list(tm.mon, str, 12); 1096b5e5868SGarrett D'Amore break; 1106b5e5868SGarrett D'Amore case T_MON: 1116b5e5868SGarrett D'Amore add_list(tm.month, str, 12); 1126b5e5868SGarrett D'Amore break; 1136b5e5868SGarrett D'Amore case T_ABDAY: 1146b5e5868SGarrett D'Amore add_list(tm.wday, str, 7); 1156b5e5868SGarrett D'Amore break; 1166b5e5868SGarrett D'Amore case T_DAY: 1176b5e5868SGarrett D'Amore add_list(tm.weekday, str, 7); 1186b5e5868SGarrett D'Amore break; 1196b5e5868SGarrett D'Amore case T_AM_PM: 1206b5e5868SGarrett D'Amore if (tm.am == NULL) { 1216b5e5868SGarrett D'Amore tm.am = str; 1226b5e5868SGarrett D'Amore } else if (tm.pm == NULL) { 1236b5e5868SGarrett D'Amore tm.pm = str; 1246b5e5868SGarrett D'Amore } else { 1256b5e5868SGarrett D'Amore errf(_("too many list elements")); 1266b5e5868SGarrett D'Amore } 1276b5e5868SGarrett D'Amore break; 1286b5e5868SGarrett D'Amore case T_ALT_DIGITS: 1296b5e5868SGarrett D'Amore case T_ERA: 1306b5e5868SGarrett D'Amore free(str); 1316b5e5868SGarrett D'Amore break; 1326b5e5868SGarrett D'Amore default: 1336b5e5868SGarrett D'Amore free(str); 1346b5e5868SGarrett D'Amore INTERR; 1356b5e5868SGarrett D'Amore break; 1366b5e5868SGarrett D'Amore } 1376b5e5868SGarrett D'Amore } 1386b5e5868SGarrett D'Amore 1396b5e5868SGarrett D'Amore void 1406b5e5868SGarrett D'Amore check_time_list(void) 1416b5e5868SGarrett D'Amore { 1426b5e5868SGarrett D'Amore switch (last_kw) { 1436b5e5868SGarrett D'Amore case T_ABMON: 1446b5e5868SGarrett D'Amore if (tm.mon[11] != NULL) 1456b5e5868SGarrett D'Amore return; 1466b5e5868SGarrett D'Amore break; 1476b5e5868SGarrett D'Amore case T_MON: 1486b5e5868SGarrett D'Amore if (tm.month[11] != NULL) 1496b5e5868SGarrett D'Amore return; 1506b5e5868SGarrett D'Amore break; 1516b5e5868SGarrett D'Amore case T_ABDAY: 1526b5e5868SGarrett D'Amore if (tm.wday[6] != NULL) 1536b5e5868SGarrett D'Amore return; 1546b5e5868SGarrett D'Amore break; 1556b5e5868SGarrett D'Amore case T_DAY: 1566b5e5868SGarrett D'Amore if (tm.weekday[6] != NULL) 1576b5e5868SGarrett D'Amore return; 1586b5e5868SGarrett D'Amore break; 1596b5e5868SGarrett D'Amore case T_AM_PM: 1606b5e5868SGarrett D'Amore if (tm.pm != NULL) 1616b5e5868SGarrett D'Amore return; 1626b5e5868SGarrett D'Amore break; 1636b5e5868SGarrett D'Amore case T_ERA: 1646b5e5868SGarrett D'Amore case T_ALT_DIGITS: 1656b5e5868SGarrett D'Amore return; 1666b5e5868SGarrett D'Amore default: 1676b5e5868SGarrett D'Amore errf(_("unknown list")); 1686b5e5868SGarrett D'Amore break; 1696b5e5868SGarrett D'Amore } 1706b5e5868SGarrett D'Amore 1716b5e5868SGarrett D'Amore errf(_("too few items in list (%d)"), last_kw); 1726b5e5868SGarrett D'Amore } 1736b5e5868SGarrett D'Amore 1746b5e5868SGarrett D'Amore void 1756b5e5868SGarrett D'Amore reset_time_list(void) 1766b5e5868SGarrett D'Amore { 1776b5e5868SGarrett D'Amore int i; 1786b5e5868SGarrett D'Amore switch (last_kw) { 1796b5e5868SGarrett D'Amore case T_ABMON: 1806b5e5868SGarrett D'Amore for (i = 0; i < 12; i++) { 1816b5e5868SGarrett D'Amore free((char *)tm.mon[i]); 1826b5e5868SGarrett D'Amore tm.mon[i] = NULL; 1836b5e5868SGarrett D'Amore } 1846b5e5868SGarrett D'Amore break; 1856b5e5868SGarrett D'Amore case T_MON: 1866b5e5868SGarrett D'Amore for (i = 0; i < 12; i++) { 1876b5e5868SGarrett D'Amore free((char *)tm.month[i]); 1886b5e5868SGarrett D'Amore tm.month[i] = NULL; 1896b5e5868SGarrett D'Amore } 1906b5e5868SGarrett D'Amore break; 1916b5e5868SGarrett D'Amore case T_ABDAY: 1926b5e5868SGarrett D'Amore for (i = 0; i < 7; i++) { 1936b5e5868SGarrett D'Amore free((char *)tm.wday[i]); 1946b5e5868SGarrett D'Amore tm.wday[i] = NULL; 1956b5e5868SGarrett D'Amore } 1966b5e5868SGarrett D'Amore break; 1976b5e5868SGarrett D'Amore case T_DAY: 1986b5e5868SGarrett D'Amore for (i = 0; i < 7; i++) { 1996b5e5868SGarrett D'Amore free((char *)tm.weekday[i]); 2006b5e5868SGarrett D'Amore tm.weekday[i] = NULL; 2016b5e5868SGarrett D'Amore } 2026b5e5868SGarrett D'Amore break; 2036b5e5868SGarrett D'Amore case T_AM_PM: 2046b5e5868SGarrett D'Amore free((char *)tm.am); 2056b5e5868SGarrett D'Amore tm.am = NULL; 2066b5e5868SGarrett D'Amore free((char *)tm.pm); 2076b5e5868SGarrett D'Amore tm.pm = NULL; 2086b5e5868SGarrett D'Amore break; 2096b5e5868SGarrett D'Amore } 2106b5e5868SGarrett D'Amore } 2116b5e5868SGarrett D'Amore 2126b5e5868SGarrett D'Amore 2136b5e5868SGarrett D'Amore void 2146b5e5868SGarrett D'Amore dump_time(void) 2156b5e5868SGarrett D'Amore { 2166b5e5868SGarrett D'Amore FILE *f; 2176b5e5868SGarrett D'Amore int i; 2186b5e5868SGarrett D'Amore 2196b5e5868SGarrett D'Amore if ((f = open_category()) == NULL) { 2206b5e5868SGarrett D'Amore return; 2216b5e5868SGarrett D'Amore } 2226b5e5868SGarrett D'Amore 2236b5e5868SGarrett D'Amore for (i = 0; i < 12; i++) { 2246b5e5868SGarrett D'Amore if (putl_category(tm.mon[i], f) == EOF) { 2256b5e5868SGarrett D'Amore return; 2266b5e5868SGarrett D'Amore } 2276b5e5868SGarrett D'Amore } 2286b5e5868SGarrett D'Amore for (i = 0; i < 12; i++) { 2296b5e5868SGarrett D'Amore if (putl_category(tm.month[i], f) == EOF) { 2306b5e5868SGarrett D'Amore return; 2316b5e5868SGarrett D'Amore } 2326b5e5868SGarrett D'Amore } 2336b5e5868SGarrett D'Amore for (i = 0; i < 7; i++) { 2346b5e5868SGarrett D'Amore if (putl_category(tm.wday[i], f) == EOF) { 2356b5e5868SGarrett D'Amore return; 2366b5e5868SGarrett D'Amore } 2376b5e5868SGarrett D'Amore } 2386b5e5868SGarrett D'Amore for (i = 0; i < 7; i++) { 2396b5e5868SGarrett D'Amore if (putl_category(tm.weekday[i], f) == EOF) { 2406b5e5868SGarrett D'Amore return; 2416b5e5868SGarrett D'Amore } 2426b5e5868SGarrett D'Amore } 2436b5e5868SGarrett D'Amore 2446b5e5868SGarrett D'Amore /* 2456b5e5868SGarrett D'Amore * NOTE: If date_fmt is not specified, then we'll default to 2466b5e5868SGarrett D'Amore * using the %c for date. This is reasonable for most 2476b5e5868SGarrett D'Amore * locales, although for reasons that I don't understand 2486b5e5868SGarrett D'Amore * Solaris historically has had a seperate format for date. 2496b5e5868SGarrett D'Amore */ 2506b5e5868SGarrett D'Amore if ((putl_category(tm.X_fmt, f) == EOF) || 2516b5e5868SGarrett D'Amore (putl_category(tm.x_fmt, f) == EOF) || 2526b5e5868SGarrett D'Amore (putl_category(tm.c_fmt, f) == EOF) || 2536b5e5868SGarrett D'Amore (putl_category(tm.am, f) == EOF) || 2546b5e5868SGarrett D'Amore (putl_category(tm.pm, f) == EOF) || 2556b5e5868SGarrett D'Amore (putl_category(tm.date_fmt ? tm.date_fmt : tm.c_fmt, f) == EOF) || 2566b5e5868SGarrett D'Amore (putl_category(tm.ampm_fmt, f) == EOF)) { 2576b5e5868SGarrett D'Amore return; 2586b5e5868SGarrett D'Amore } 2596b5e5868SGarrett D'Amore close_category(f); 2606b5e5868SGarrett D'Amore } 261