1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
14  */
15 
16 /*
17  * This file implements the 2008 newlocale and friends handling. It is
18  * private to libc.
19  */
20 #ifndef	_LOCALEIMPL_H_
21 #define	_LOCALEIMPL_H_
22 
23 #ifndef _LCONV_C99
24 #define	_LCONV_C99	/* so we get all the extensions */
25 #endif
26 
27 #include <sys/types.h>
28 #include <locale.h>
29 #include <xlocale.h>
30 #include "setlocale.h"
31 #include "runetype.h"
32 
33 /* private locale structures */
34 
35 /*
36  * Because some locale data is rather ahem.. large, we would like to keep
37  * reference counts on it.  We create an abstract header (locdata) structure
38  * which keeps a point to the opaque per-category data, along with a reference
39  * count to it.  To be threadsafe, we will use atomics when holding it or
40  * freeing it.  (This only occurs when locale objects are created or destroyed,
41  * so there should be no performance impact on hot code paths.  If your code
42  * uses locale_t creation/destruction on a hot code path, its broken.  But
43  * even so, the atomic and reference counting will probably *greatly* improve
44  * your life as bootstrapping locale data from files is quite expensive.
45  */
46 
47 #define	NLOCDATA	4
48 struct locdata {
49 	char		l_lname[ENCODING_LEN+1];	/* locale name */
50 	void		*l_data[NLOCDATA];		/* storage area */
51 	void		*l_map;				/* mapped file */
52 	size_t		l_map_len;
53 	struct locdata	*l_next;			/* link cached list */
54 	int		l_cached;			/* nonzero if cached */
55 };
56 
57 
58 struct _locale {
59 	struct locdata	*locdata[LC_ALL];
60 	struct _locale	*next;
61 	int		on_list;	/* on linked list */
62 	char		locname[(ENCODING_LEN+1)*NLOCDATA + 1];
63 
64 	/*
65 	 * Convenience pointers.
66 	 */
67 	const struct lc_ctype		*ctype;
68 	const struct lc_collate		*collate;
69 	const struct lc_messages	*messages;
70 	const struct lc_monetary	*monetary;
71 	const struct lc_numeric		*numeric;
72 	const struct lc_time		*time;
73 	const _RuneLocale		*runelocale;
74 
75 	/*
76 	 * The loaded value is used for localeconv.  In paticular, when
77 	 * when we change the value of one of the above categories, we will
78 	 * also need to update the lconv structure.  The loaded bit indicates
79 	 * that the lconv structure is "current" for that category.  It's
80 	 * sort of an "inverse dirty" bit.
81 	 */
82 	int		loaded[LC_ALL];
83 	struct lconv	lconv;
84 };
85 
86 
87 struct locdata *__locdata_alloc(const char *, size_t);
88 void __locdata_free(struct locdata *);
89 struct locdata *__locdata_get_cache(int, const char *);
90 void __locdata_set_cache(int, struct locdata *);
91 
92 struct locdata *__lc_numeric_load(const char *name);
93 struct locdata *__lc_monetary_load(const char *name);
94 struct locdata *__lc_messages_load(const char *name);
95 struct locdata *__lc_time_load(const char *name);
96 struct locdata *__lc_ctype_load(const char *name);
97 struct locdata *__lc_collate_load(const char *name);
98 
99 extern struct locdata	__posix_numeric_locdata;
100 extern struct locdata	__posix_monetary_locdata;
101 extern struct locdata	__posix_messages_locdata;
102 extern struct locdata	__posix_time_locdata;
103 extern struct locdata	__posix_ctype_locdata;
104 extern struct locdata	__posix_collate_locdata;
105 extern locale_t ___global_locale;
106 
107 #endif	/* _LOCALEIMPL_H_ */
108