1/*-
2 * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
3 * Copyright (c) 1997 FreeBSD Inc.
4 * All rights reserved.
5 *
6 * Copyright (c) 2011 The FreeBSD Foundation
7 * All rights reserved.
8 * Portions of this software were developed by David Chisnall
9 * under sponsorship from the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36#include <stddef.h>
37
38#include "ldpart.h"
39#include "timelocal.h"
40
41struct xlocale_time {
42	struct xlocale_component header;
43	char *buffer;
44	struct lc_time_T locale;
45};
46
47struct xlocale_time __xlocale_global_time;
48
49#define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *))
50
51static const struct lc_time_T	_C_time_locale = {
52	{
53		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
54		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
55	}, {
56		"January", "February", "March", "April", "May", "June",
57		"July", "August", "September", "October", "November", "December"
58	}, {
59		"Sun", "Mon", "Tue", "Wed",
60		"Thu", "Fri", "Sat"
61	}, {
62		"Sunday", "Monday", "Tuesday", "Wednesday",
63		"Thursday", "Friday", "Saturday"
64	},
65
66	/* X_fmt */
67	"%H:%M:%S",
68
69	/*
70	 * x_fmt
71	 * Since the C language standard calls for
72	 * "date, using locale's date format," anything goes.
73	 * Using just numbers (as here) makes Quakers happier;
74	 * it's also compatible with SVR4.
75	 */
76	"%m/%d/%y",
77
78	/*
79	 * c_fmt
80	 */
81	"%a %b %e %H:%M:%S %Y",
82
83	/* am */
84	"AM",
85
86	/* pm */
87	"PM",
88
89	/* date_fmt */
90	"%a %b %e %H:%M:%S %Z %Y",
91
92	/* alt_month
93	 * Standalone months forms for %OB
94	 */
95	{
96		"January", "February", "March", "April", "May", "June",
97		"July", "August", "September", "October", "November", "December"
98	},
99
100	/* md_order
101	 * Month / day order in dates
102	 */
103	"md",
104
105	/* ampm_fmt
106	 * To determine 12-hour clock format time (empty, if N/A)
107	 */
108	"%I:%M:%S %p"
109};
110
111static void destruct_time(void *v)
112{
113	struct xlocale_time *l = v;
114	if (l->buffer)
115		free(l->buffer);
116	free(l);
117}
118
119#include <stdio.h>
120struct lc_time_T *
121__get_current_time_locale(locale_t loc)
122{
123	return (loc->using_time_locale
124		? &((struct xlocale_time *)loc->components[XLC_TIME])->locale
125		: (struct lc_time_T *)&_C_time_locale);
126}
127
128static int
129time_load_locale(struct xlocale_time *l, int *using_locale, const char *name)
130{
131	struct lc_time_T *time_locale = &l->locale;
132	return (__part_load_locale(name, using_locale,
133			&l->buffer, "LC_TIME",
134			LCTIME_SIZE, LCTIME_SIZE,
135			(const char **)time_locale));
136}
137int
138__time_load_locale(const char *name)
139{
140	return time_load_locale(&__xlocale_global_time,
141			&__xlocale_global_locale.using_time_locale, name);
142}
143void* __time_load(const char* name, locale_t loc)
144{
145	struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1);
146	new->header.header.destructor = destruct_time;
147	if (time_load_locale(new, &loc->using_time_locale, name) == _LDP_ERROR)
148	{
149		xlocale_release(new);
150		return NULL;
151	}
152	return new;
153}
154
155