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
init_time(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
add_time_str(wchar_t * wcs)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
add_list(const char * ptr[],char * str,int limit)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
add_time_list(wchar_t * wcs)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
check_time_list(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
reset_time_list(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
dump_time(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