xref: /illumos-gate/usr/src/cmd/localedef/time.c (revision 7262c8a6)
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 /*
132d08521bSGarrett D'Amore  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
14e1508819SYuri Pankov  * Copyright 2017 Nexenta Systems, Inc.
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 
312d08521bSGarrett 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 		/*
65e1508819SYuri Pankov 		 * 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. */
74e1508819SYuri Pankov 		free(str);
756b5e5868SGarrett D'Amore 		break;
766b5e5868SGarrett D'Amore 	default:
776b5e5868SGarrett D'Amore 		free(str);
786b5e5868SGarrett D'Amore 		INTERR;
796b5e5868SGarrett D'Amore 		break;
806b5e5868SGarrett D'Amore 	}
816b5e5868SGarrett D'Amore }
826b5e5868SGarrett D'Amore 
836b5e5868SGarrett D'Amore static void
add_list(const char * ptr[],char * str,int limit)846b5e5868SGarrett D'Amore add_list(const char *ptr[], char *str, int limit)
856b5e5868SGarrett D'Amore {
866b5e5868SGarrett D'Amore 	int	i;
876b5e5868SGarrett D'Amore 	for (i = 0; i < limit; i++) {
886b5e5868SGarrett D'Amore 		if (ptr[i] == NULL) {
896b5e5868SGarrett D'Amore 			ptr[i] = str;
906b5e5868SGarrett D'Amore 			return;
916b5e5868SGarrett D'Amore 		}
926b5e5868SGarrett D'Amore 	}
936b5e5868SGarrett D'Amore 	errf(_("too many list elements"));
946b5e5868SGarrett D'Amore }
956b5e5868SGarrett D'Amore 
966b5e5868SGarrett D'Amore void
add_time_list(wchar_t * wcs)976b5e5868SGarrett D'Amore add_time_list(wchar_t *wcs)
986b5e5868SGarrett D'Amore {
996b5e5868SGarrett D'Amore 	char *str;
1006b5e5868SGarrett D'Amore 
1016b5e5868SGarrett D'Amore 	if ((str = to_mb_string(wcs)) == NULL) {
1026b5e5868SGarrett D'Amore 		INTERR;
1036b5e5868SGarrett D'Amore 		return;
1046b5e5868SGarrett D'Amore 	}
1056b5e5868SGarrett D'Amore 	free(wcs);
1066b5e5868SGarrett D'Amore 
1076b5e5868SGarrett D'Amore 	switch (last_kw) {
1086b5e5868SGarrett D'Amore 	case T_ABMON:
1096b5e5868SGarrett D'Amore 		add_list(tm.mon, str, 12);
1106b5e5868SGarrett D'Amore 		break;
1116b5e5868SGarrett D'Amore 	case T_MON:
1126b5e5868SGarrett D'Amore 		add_list(tm.month, str, 12);
1136b5e5868SGarrett D'Amore 		break;
1146b5e5868SGarrett D'Amore 	case T_ABDAY:
1156b5e5868SGarrett D'Amore 		add_list(tm.wday, str, 7);
1166b5e5868SGarrett D'Amore 		break;
1176b5e5868SGarrett D'Amore 	case T_DAY:
1186b5e5868SGarrett D'Amore 		add_list(tm.weekday, str, 7);
1196b5e5868SGarrett D'Amore 		break;
1206b5e5868SGarrett D'Amore 	case T_AM_PM:
1216b5e5868SGarrett D'Amore 		if (tm.am == NULL) {
1226b5e5868SGarrett D'Amore 			tm.am = str;
1236b5e5868SGarrett D'Amore 		} else if (tm.pm == NULL) {
1246b5e5868SGarrett D'Amore 			tm.pm = str;
1256b5e5868SGarrett D'Amore 		} else {
1266b5e5868SGarrett D'Amore 			errf(_("too many list elements"));
127e1508819SYuri Pankov 			free(str);
1286b5e5868SGarrett D'Amore 		}
1296b5e5868SGarrett D'Amore 		break;
1306b5e5868SGarrett D'Amore 	case T_ALT_DIGITS:
1316b5e5868SGarrett D'Amore 	case T_ERA:
1326b5e5868SGarrett D'Amore 		free(str);
1336b5e5868SGarrett D'Amore 		break;
1346b5e5868SGarrett D'Amore 	default:
1356b5e5868SGarrett D'Amore 		free(str);
1366b5e5868SGarrett D'Amore 		INTERR;
1376b5e5868SGarrett D'Amore 		break;
1386b5e5868SGarrett D'Amore 	}
1396b5e5868SGarrett D'Amore }
1406b5e5868SGarrett D'Amore 
1416b5e5868SGarrett D'Amore void
check_time_list(void)1426b5e5868SGarrett D'Amore check_time_list(void)
1436b5e5868SGarrett D'Amore {
1446b5e5868SGarrett D'Amore 	switch (last_kw) {
1456b5e5868SGarrett D'Amore 	case T_ABMON:
1466b5e5868SGarrett D'Amore 		if (tm.mon[11] != NULL)
1476b5e5868SGarrett D'Amore 			return;
1486b5e5868SGarrett D'Amore 		break;
1496b5e5868SGarrett D'Amore 	case T_MON:
1506b5e5868SGarrett D'Amore 		if (tm.month[11] != NULL)
1516b5e5868SGarrett D'Amore 			return;
1526b5e5868SGarrett D'Amore 		break;
1536b5e5868SGarrett D'Amore 	case T_ABDAY:
1546b5e5868SGarrett D'Amore 		if (tm.wday[6] != NULL)
1556b5e5868SGarrett D'Amore 			return;
1566b5e5868SGarrett D'Amore 		break;
1576b5e5868SGarrett D'Amore 	case T_DAY:
1586b5e5868SGarrett D'Amore 		if (tm.weekday[6] != NULL)
1596b5e5868SGarrett D'Amore 			return;
1606b5e5868SGarrett D'Amore 		break;
1616b5e5868SGarrett D'Amore 	case T_AM_PM:
1626b5e5868SGarrett D'Amore 		if (tm.pm != NULL)
1636b5e5868SGarrett D'Amore 			return;
1646b5e5868SGarrett D'Amore 		break;
1656b5e5868SGarrett D'Amore 	case T_ERA:
1666b5e5868SGarrett D'Amore 	case T_ALT_DIGITS:
1676b5e5868SGarrett D'Amore 		return;
1686b5e5868SGarrett D'Amore 	default:
1696b5e5868SGarrett D'Amore 		errf(_("unknown list"));
1706b5e5868SGarrett D'Amore 		break;
1716b5e5868SGarrett D'Amore 	}
1726b5e5868SGarrett D'Amore 
1736b5e5868SGarrett D'Amore 	errf(_("too few items in list (%d)"), last_kw);
1746b5e5868SGarrett D'Amore }
1756b5e5868SGarrett D'Amore 
1766b5e5868SGarrett D'Amore void
reset_time_list(void)1776b5e5868SGarrett D'Amore reset_time_list(void)
1786b5e5868SGarrett D'Amore {
1796b5e5868SGarrett D'Amore 	int i;
1806b5e5868SGarrett D'Amore 	switch (last_kw) {
1816b5e5868SGarrett D'Amore 	case T_ABMON:
1826b5e5868SGarrett D'Amore 		for (i = 0; i < 12; i++) {
1836b5e5868SGarrett D'Amore 			free((char *)tm.mon[i]);
1846b5e5868SGarrett D'Amore 			tm.mon[i] = NULL;
1856b5e5868SGarrett D'Amore 		}
1866b5e5868SGarrett D'Amore 		break;
1876b5e5868SGarrett D'Amore 	case T_MON:
1886b5e5868SGarrett D'Amore 		for (i = 0; i < 12; i++) {
1896b5e5868SGarrett D'Amore 			free((char *)tm.month[i]);
1906b5e5868SGarrett D'Amore 			tm.month[i] = NULL;
1916b5e5868SGarrett D'Amore 		}
1926b5e5868SGarrett D'Amore 		break;
1936b5e5868SGarrett D'Amore 	case T_ABDAY:
1946b5e5868SGarrett D'Amore 		for (i = 0; i < 7; i++) {
1956b5e5868SGarrett D'Amore 			free((char *)tm.wday[i]);
1966b5e5868SGarrett D'Amore 			tm.wday[i] = NULL;
1976b5e5868SGarrett D'Amore 		}
1986b5e5868SGarrett D'Amore 		break;
1996b5e5868SGarrett D'Amore 	case T_DAY:
2006b5e5868SGarrett D'Amore 		for (i = 0; i < 7; i++) {
2016b5e5868SGarrett D'Amore 			free((char *)tm.weekday[i]);
2026b5e5868SGarrett D'Amore 			tm.weekday[i] = NULL;
2036b5e5868SGarrett D'Amore 		}
2046b5e5868SGarrett D'Amore 		break;
2056b5e5868SGarrett D'Amore 	case T_AM_PM:
2066b5e5868SGarrett D'Amore 		free((char *)tm.am);
2076b5e5868SGarrett D'Amore 		tm.am = NULL;
2086b5e5868SGarrett D'Amore 		free((char *)tm.pm);
2096b5e5868SGarrett D'Amore 		tm.pm = NULL;
2106b5e5868SGarrett D'Amore 		break;
2116b5e5868SGarrett D'Amore 	}
2126b5e5868SGarrett D'Amore }
2136b5e5868SGarrett D'Amore 
2146b5e5868SGarrett D'Amore 
2156b5e5868SGarrett D'Amore void
dump_time(void)2166b5e5868SGarrett D'Amore dump_time(void)
2176b5e5868SGarrett D'Amore {
2186b5e5868SGarrett D'Amore 	FILE *f;
2196b5e5868SGarrett D'Amore 	int i;
2206b5e5868SGarrett D'Amore 
2216b5e5868SGarrett D'Amore 	if ((f = open_category()) == NULL) {
2226b5e5868SGarrett D'Amore 		return;
2236b5e5868SGarrett D'Amore 	}
2246b5e5868SGarrett D'Amore 
2256b5e5868SGarrett D'Amore 	for (i = 0; i < 12; i++) {
2266b5e5868SGarrett D'Amore 		if (putl_category(tm.mon[i], f) == EOF) {
2276b5e5868SGarrett D'Amore 			return;
2286b5e5868SGarrett D'Amore 		}
2296b5e5868SGarrett D'Amore 	}
2306b5e5868SGarrett D'Amore 	for (i = 0; i < 12; i++) {
2316b5e5868SGarrett D'Amore 		if (putl_category(tm.month[i], f) == EOF) {
2326b5e5868SGarrett D'Amore 			return;
2336b5e5868SGarrett D'Amore 		}
2346b5e5868SGarrett D'Amore 	}
2356b5e5868SGarrett D'Amore 	for (i = 0; i < 7; i++) {
2366b5e5868SGarrett D'Amore 		if (putl_category(tm.wday[i], f) == EOF) {
2376b5e5868SGarrett D'Amore 			return;
2386b5e5868SGarrett D'Amore 		}
2396b5e5868SGarrett D'Amore 	}
2406b5e5868SGarrett D'Amore 	for (i = 0; i < 7; i++) {
2416b5e5868SGarrett D'Amore 		if (putl_category(tm.weekday[i], f) == EOF) {
2426b5e5868SGarrett D'Amore 			return;
2436b5e5868SGarrett D'Amore 		}
2446b5e5868SGarrett D'Amore 	}
2456b5e5868SGarrett D'Amore 
2466b5e5868SGarrett D'Amore 	/*
2476b5e5868SGarrett D'Amore 	 * NOTE: If date_fmt is not specified, then we'll default to
2486b5e5868SGarrett D'Amore 	 * using the %c for date.  This is reasonable for most
2496b5e5868SGarrett D'Amore 	 * locales, although for reasons that I don't understand
250*7262c8a6SYuri Pankov 	 * Solaris historically has had a separate format for date.
2516b5e5868SGarrett D'Amore 	 */
2526b5e5868SGarrett D'Amore 	if ((putl_category(tm.X_fmt, f) == EOF) ||
2536b5e5868SGarrett D'Amore 	    (putl_category(tm.x_fmt, f) == EOF) ||
2546b5e5868SGarrett D'Amore 	    (putl_category(tm.c_fmt, f) == EOF) ||
2556b5e5868SGarrett D'Amore 	    (putl_category(tm.am, f) == EOF) ||
2566b5e5868SGarrett D'Amore 	    (putl_category(tm.pm, f) == EOF) ||
2576b5e5868SGarrett D'Amore 	    (putl_category(tm.date_fmt ? tm.date_fmt : tm.c_fmt, f) == EOF) ||
2586b5e5868SGarrett D'Amore 	    (putl_category(tm.ampm_fmt, f) == EOF)) {
2596b5e5868SGarrett D'Amore 		return;
2606b5e5868SGarrett D'Amore 	}
2616b5e5868SGarrett D'Amore 	close_category(f);
2626b5e5868SGarrett D'Amore }
263