xref: /illumos-gate/usr/src/lib/libc/port/i18n/gettext.c (revision b599bd93)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52e145884Sraf  * Common Development and Distribution License (the "License").
62e145884Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
212e145884Sraf 
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*b599bd93SRobert Mustacchi /*
27*b599bd93SRobert Mustacchi  * Copyright 2015 Joyent, Inc.
28*b599bd93SRobert Mustacchi  */
297c478bd9Sstevel@tonic-gate 
307257d1b4Sraf #pragma weak _bindtextdomain = bindtextdomain
317257d1b4Sraf #pragma weak _textdomain = textdomain
327257d1b4Sraf #pragma weak _gettext = gettext
337257d1b4Sraf #pragma weak _dgettext = dgettext
347257d1b4Sraf #pragma weak _dcgettext = dcgettext
357257d1b4Sraf #pragma weak _ngettext = ngettext
367257d1b4Sraf #pragma weak _dngettext = dngettext
377257d1b4Sraf #pragma weak _dcngettext = dcngettext
387257d1b4Sraf #pragma weak _bind_textdomain_codeset = bind_textdomain_codeset
397257d1b4Sraf 
407257d1b4Sraf #include "lint.h"
417c478bd9Sstevel@tonic-gate #include "mtlib.h"
427c478bd9Sstevel@tonic-gate #include <errno.h>
437c478bd9Sstevel@tonic-gate #include <ctype.h>
447c478bd9Sstevel@tonic-gate #include <locale.h>
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <stdlib.h>
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <sys/param.h>
497c478bd9Sstevel@tonic-gate #include <libintl.h>
507c478bd9Sstevel@tonic-gate #include <thread.h>
517c478bd9Sstevel@tonic-gate #include <synch.h>
527c478bd9Sstevel@tonic-gate #include "libc.h"
537c478bd9Sstevel@tonic-gate #include "_loc_path.h"
547c478bd9Sstevel@tonic-gate #include "msgfmt.h"
557c478bd9Sstevel@tonic-gate #include "gettext.h"
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #define	INIT_GT(def) \
587c478bd9Sstevel@tonic-gate 	if (!global_gt) { \
597c478bd9Sstevel@tonic-gate 		global_gt = (Gettext_t *)calloc(1, sizeof (Gettext_t)); \
607c478bd9Sstevel@tonic-gate 		if (global_gt) \
617c478bd9Sstevel@tonic-gate 			global_gt->cur_domain = (char *)default_domain; \
627c478bd9Sstevel@tonic-gate 		else { \
6398c1a6b4Sraf 			callout_lock_exit(); \
647c478bd9Sstevel@tonic-gate 			return ((def)); \
657c478bd9Sstevel@tonic-gate 		} \
667c478bd9Sstevel@tonic-gate 	}
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate const char	*defaultbind = DEFAULT_BINDING;
697c478bd9Sstevel@tonic-gate const char	default_domain[] = DEFAULT_DOMAIN;
707c478bd9Sstevel@tonic-gate Gettext_t	*global_gt = NULL;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate char *
bindtextdomain(const char * domain,const char * binding)737257d1b4Sraf bindtextdomain(const char *domain, const char *binding)
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	char	*res;
767c478bd9Sstevel@tonic-gate 
7798c1a6b4Sraf 	callout_lock_enter();
787c478bd9Sstevel@tonic-gate 	INIT_GT(NULL);
797c478bd9Sstevel@tonic-gate 	res = _real_bindtextdomain_u(domain, binding, TP_BINDING);
8098c1a6b4Sraf 	callout_lock_exit();
817c478bd9Sstevel@tonic-gate 	return (res);
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate char *
bind_textdomain_codeset(const char * domain,const char * codeset)857257d1b4Sraf bind_textdomain_codeset(const char *domain, const char *codeset)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate 	char	*res;
887c478bd9Sstevel@tonic-gate 
8998c1a6b4Sraf 	callout_lock_enter();
907c478bd9Sstevel@tonic-gate 	INIT_GT(NULL);
917c478bd9Sstevel@tonic-gate 	res = _real_bindtextdomain_u(domain, codeset, TP_CODESET);
9298c1a6b4Sraf 	callout_lock_exit();
937c478bd9Sstevel@tonic-gate 	return (res);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * textdomain() sets or queries the name of the current domain of
987c478bd9Sstevel@tonic-gate  * the active LC_MESSAGES locale category.
997c478bd9Sstevel@tonic-gate  */
1007c478bd9Sstevel@tonic-gate char *
textdomain(const char * domain)1017257d1b4Sraf textdomain(const char *domain)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	char	*res;
1047c478bd9Sstevel@tonic-gate 	char	tmp_domain[TEXTDOMAINMAX + 1];
1057c478bd9Sstevel@tonic-gate 
10698c1a6b4Sraf 	callout_lock_enter();
1077c478bd9Sstevel@tonic-gate 	INIT_GT(NULL);
1087c478bd9Sstevel@tonic-gate 	res = _textdomain_u(domain, tmp_domain);
1097c478bd9Sstevel@tonic-gate 	if (res == NULL) {
11098c1a6b4Sraf 		callout_lock_exit();
1117c478bd9Sstevel@tonic-gate 		return (NULL);
1127c478bd9Sstevel@tonic-gate 	}
11398c1a6b4Sraf 	callout_lock_exit();
1147c478bd9Sstevel@tonic-gate 	return (CURRENT_DOMAIN(global_gt));
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * gettext() is a pass-thru to _real_gettext_u() with a NULL pointer passed
1197c478bd9Sstevel@tonic-gate  * for domain and LC_MESSAGES passed for category.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate char *
gettext(const char * msg_id)1227257d1b4Sraf gettext(const char *msg_id)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate 	char	*res;
1257c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
1267c478bd9Sstevel@tonic-gate 
12798c1a6b4Sraf 	callout_lock_enter();
1287c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msg_id);
129*b599bd93SRobert Mustacchi 	res = _real_gettext_u(NULL, msg_id, NULL, 0, LC_MESSAGES, 0, NULL);
13098c1a6b4Sraf 	callout_lock_exit();
1317c478bd9Sstevel@tonic-gate 	errno = errno_save;
1327c478bd9Sstevel@tonic-gate 	return (res);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * In dcgettext() call, domain is valid only for this call.
1387c478bd9Sstevel@tonic-gate  */
1397c478bd9Sstevel@tonic-gate char *
dgettext(const char * domain,const char * msg_id)1407257d1b4Sraf dgettext(const char *domain, const char *msg_id)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	char	*res;
1437c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
1447c478bd9Sstevel@tonic-gate 
14598c1a6b4Sraf 	callout_lock_enter();
1467c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msg_id);
147*b599bd93SRobert Mustacchi 	res = _real_gettext_u(domain, msg_id, NULL, 0, LC_MESSAGES, 0, NULL);
148*b599bd93SRobert Mustacchi 	callout_lock_exit();
149*b599bd93SRobert Mustacchi 	errno = errno_save;
150*b599bd93SRobert Mustacchi 	return (res);
151*b599bd93SRobert Mustacchi }
152*b599bd93SRobert Mustacchi 
153*b599bd93SRobert Mustacchi char *
dgettext_l(const char * domain,const char * msg_id,locale_t loc)154*b599bd93SRobert Mustacchi dgettext_l(const char *domain, const char *msg_id, locale_t loc)
155*b599bd93SRobert Mustacchi {
156*b599bd93SRobert Mustacchi 	char	*res;
157*b599bd93SRobert Mustacchi 	int	errno_save = errno;
158*b599bd93SRobert Mustacchi 
159*b599bd93SRobert Mustacchi 	callout_lock_enter();
160*b599bd93SRobert Mustacchi 	INIT_GT((char *)msg_id);
161*b599bd93SRobert Mustacchi 	res = _real_gettext_u(domain, msg_id, NULL, 0, LC_MESSAGES, 0, loc);
16298c1a6b4Sraf 	callout_lock_exit();
1637c478bd9Sstevel@tonic-gate 	errno = errno_save;
1647c478bd9Sstevel@tonic-gate 	return (res);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate char *
dcgettext(const char * domain,const char * msg_id,const int category)1687257d1b4Sraf dcgettext(const char *domain, const char *msg_id, const int category)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	char	*res;
1717c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
1727c478bd9Sstevel@tonic-gate 
17398c1a6b4Sraf 	callout_lock_enter();
1747c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msg_id);
175*b599bd93SRobert Mustacchi 	res = _real_gettext_u(domain, msg_id, NULL, 0, category, 0, NULL);
17698c1a6b4Sraf 	callout_lock_exit();
1777c478bd9Sstevel@tonic-gate 	errno = errno_save;
1787c478bd9Sstevel@tonic-gate 	return (res);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate char *
ngettext(const char * msgid1,const char * msgid2,unsigned long int n)1827257d1b4Sraf ngettext(const char *msgid1, const char *msgid2, unsigned long int n)
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	char	*res;
1857c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
1867c478bd9Sstevel@tonic-gate 
18798c1a6b4Sraf 	callout_lock_enter();
1887c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msgid1);
189*b599bd93SRobert Mustacchi 	res = _real_gettext_u(NULL, msgid1, msgid2, n, LC_MESSAGES, 1, NULL);
19098c1a6b4Sraf 	callout_lock_exit();
1917c478bd9Sstevel@tonic-gate 	errno = errno_save;
1927c478bd9Sstevel@tonic-gate 	return (res);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate char *
dngettext(const char * domain,const char * msgid1,const char * msgid2,unsigned long int n)1967257d1b4Sraf dngettext(const char *domain, const char *msgid1, const char *msgid2,
1977c478bd9Sstevel@tonic-gate 	unsigned long int n)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate 	char	*res;
2007c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
2017c478bd9Sstevel@tonic-gate 
20298c1a6b4Sraf 	callout_lock_enter();
2037c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msgid1);
204*b599bd93SRobert Mustacchi 	res = _real_gettext_u(domain, msgid1, msgid2, n, LC_MESSAGES, 1, NULL);
20598c1a6b4Sraf 	callout_lock_exit();
2067c478bd9Sstevel@tonic-gate 	errno = errno_save;
2077c478bd9Sstevel@tonic-gate 	return (res);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate char *
dcngettext(const char * domain,const char * msgid1,const char * msgid2,unsigned long int n,int category)2117257d1b4Sraf dcngettext(const char *domain, const char *msgid1, const char *msgid2,
2127c478bd9Sstevel@tonic-gate 	unsigned long int n, int category)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	char	*res;
2157c478bd9Sstevel@tonic-gate 	int	errno_save = errno;
2167c478bd9Sstevel@tonic-gate 
21798c1a6b4Sraf 	callout_lock_enter();
2187c478bd9Sstevel@tonic-gate 	INIT_GT((char *)msgid1);
219*b599bd93SRobert Mustacchi 	res = _real_gettext_u(domain, msgid1, msgid2, n, category, 1, NULL);
22098c1a6b4Sraf 	callout_lock_exit();
2217c478bd9Sstevel@tonic-gate 	errno = errno_save;
2227c478bd9Sstevel@tonic-gate 	return (res);
2237c478bd9Sstevel@tonic-gate }
224