1*3d8817e4Smiod /* Compatibility code for gettext-using-catgets interface.
2*3d8817e4Smiod Copyright (C) 1995, 1997 Free Software Foundation, Inc.
3*3d8817e4Smiod
4*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
5*3d8817e4Smiod it under the terms of the GNU General Public License as published by
6*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
7*3d8817e4Smiod any later version.
8*3d8817e4Smiod
9*3d8817e4Smiod This program is distributed in the hope that it will be useful,
10*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
11*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*3d8817e4Smiod GNU General Public License for more details.
13*3d8817e4Smiod
14*3d8817e4Smiod You should have received a copy of the GNU General Public License
15*3d8817e4Smiod along with this program; if not, write to the Free Software Foundation,
16*3d8817e4Smiod Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17*3d8817e4Smiod
18*3d8817e4Smiod #ifdef HAVE_CONFIG_H
19*3d8817e4Smiod # include <config.h>
20*3d8817e4Smiod #endif
21*3d8817e4Smiod
22*3d8817e4Smiod #include <stdio.h>
23*3d8817e4Smiod
24*3d8817e4Smiod #ifdef STDC_HEADERS
25*3d8817e4Smiod # include <stdlib.h>
26*3d8817e4Smiod # include <string.h>
27*3d8817e4Smiod #else
28*3d8817e4Smiod char *getenv ();
29*3d8817e4Smiod # ifdef HAVE_MALLOC_H
30*3d8817e4Smiod # include <malloc.h>
31*3d8817e4Smiod # endif
32*3d8817e4Smiod #endif
33*3d8817e4Smiod
34*3d8817e4Smiod #ifdef HAVE_NL_TYPES_H
35*3d8817e4Smiod # include <nl_types.h>
36*3d8817e4Smiod #endif
37*3d8817e4Smiod
38*3d8817e4Smiod #include "libgettext.h"
39*3d8817e4Smiod
40*3d8817e4Smiod /* @@ end of prolog @@ */
41*3d8817e4Smiod
42*3d8817e4Smiod /* XPG3 defines the result of `setlocale (category, NULL)' as:
43*3d8817e4Smiod ``Directs `setlocale()' to query `category' and return the current
44*3d8817e4Smiod setting of `local'.''
45*3d8817e4Smiod However it does not specify the exact format. And even worse: POSIX
46*3d8817e4Smiod defines this not at all. So we can use this feature only on selected
47*3d8817e4Smiod system (e.g. those using GNU C Library). */
48*3d8817e4Smiod #ifdef _LIBC
49*3d8817e4Smiod # define HAVE_LOCALE_NULL
50*3d8817e4Smiod #endif
51*3d8817e4Smiod
52*3d8817e4Smiod /* The catalog descriptor. */
53*3d8817e4Smiod static nl_catd catalog = (nl_catd) -1;
54*3d8817e4Smiod
55*3d8817e4Smiod /* Name of the default catalog. */
56*3d8817e4Smiod static const char default_catalog_name[] = "messages";
57*3d8817e4Smiod
58*3d8817e4Smiod /* Name of currently used catalog. */
59*3d8817e4Smiod static const char *catalog_name = default_catalog_name;
60*3d8817e4Smiod
61*3d8817e4Smiod /* Get ID for given string. If not found return -1. */
62*3d8817e4Smiod static int msg_to_cat_id PARAMS ((const char *msg));
63*3d8817e4Smiod
64*3d8817e4Smiod /* Substitution for systems lacking this function in their C library. */
65*3d8817e4Smiod #if !_LIBC && !HAVE_STPCPY
66*3d8817e4Smiod static char *stpcpy PARAMS ((char *dest, const char *src));
67*3d8817e4Smiod #endif
68*3d8817e4Smiod
69*3d8817e4Smiod
70*3d8817e4Smiod /* Set currently used domain/catalog. */
71*3d8817e4Smiod char *
textdomain(domainname)72*3d8817e4Smiod textdomain (domainname)
73*3d8817e4Smiod const char *domainname;
74*3d8817e4Smiod {
75*3d8817e4Smiod nl_catd new_catalog;
76*3d8817e4Smiod char *new_name;
77*3d8817e4Smiod size_t new_name_len;
78*3d8817e4Smiod char *lang;
79*3d8817e4Smiod
80*3d8817e4Smiod #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES \
81*3d8817e4Smiod && defined HAVE_LOCALE_NULL
82*3d8817e4Smiod lang = setlocale (LC_MESSAGES, NULL);
83*3d8817e4Smiod #else
84*3d8817e4Smiod lang = getenv ("LC_ALL");
85*3d8817e4Smiod if (lang == NULL || lang[0] == '\0')
86*3d8817e4Smiod {
87*3d8817e4Smiod lang = getenv ("LC_MESSAGES");
88*3d8817e4Smiod if (lang == NULL || lang[0] == '\0')
89*3d8817e4Smiod lang = getenv ("LANG");
90*3d8817e4Smiod }
91*3d8817e4Smiod #endif
92*3d8817e4Smiod if (lang == NULL || lang[0] == '\0')
93*3d8817e4Smiod lang = "C";
94*3d8817e4Smiod
95*3d8817e4Smiod /* See whether name of currently used domain is asked. */
96*3d8817e4Smiod if (domainname == NULL)
97*3d8817e4Smiod return (char *) catalog_name;
98*3d8817e4Smiod
99*3d8817e4Smiod if (domainname[0] == '\0')
100*3d8817e4Smiod domainname = default_catalog_name;
101*3d8817e4Smiod
102*3d8817e4Smiod /* Compute length of added path element. */
103*3d8817e4Smiod new_name_len = sizeof (LOCALEDIR) - 1 + 1 + strlen (lang)
104*3d8817e4Smiod + sizeof ("/LC_MESSAGES/") - 1 + sizeof (PACKAGE) - 1
105*3d8817e4Smiod + sizeof (".cat");
106*3d8817e4Smiod
107*3d8817e4Smiod new_name = (char *) malloc (new_name_len);
108*3d8817e4Smiod if (new_name == NULL)
109*3d8817e4Smiod return NULL;
110*3d8817e4Smiod
111*3d8817e4Smiod strcpy (new_name, PACKAGE);
112*3d8817e4Smiod new_catalog = catopen (new_name, 0);
113*3d8817e4Smiod
114*3d8817e4Smiod if (new_catalog == (nl_catd) -1)
115*3d8817e4Smiod {
116*3d8817e4Smiod /* NLSPATH search didn't work, try absolute path */
117*3d8817e4Smiod sprintf (new_name, "%s/%s/LC_MESSAGES/%s.cat", LOCALEDIR, lang,
118*3d8817e4Smiod PACKAGE);
119*3d8817e4Smiod new_catalog = catopen (new_name, 0);
120*3d8817e4Smiod
121*3d8817e4Smiod if (new_catalog == (nl_catd) -1)
122*3d8817e4Smiod {
123*3d8817e4Smiod free (new_name);
124*3d8817e4Smiod return (char *) catalog_name;
125*3d8817e4Smiod }
126*3d8817e4Smiod }
127*3d8817e4Smiod
128*3d8817e4Smiod /* Close old catalog. */
129*3d8817e4Smiod if (catalog != (nl_catd) -1)
130*3d8817e4Smiod catclose (catalog);
131*3d8817e4Smiod if (catalog_name != default_catalog_name)
132*3d8817e4Smiod free ((char *) catalog_name);
133*3d8817e4Smiod
134*3d8817e4Smiod catalog = new_catalog;
135*3d8817e4Smiod catalog_name = new_name;
136*3d8817e4Smiod
137*3d8817e4Smiod return (char *) catalog_name;
138*3d8817e4Smiod }
139*3d8817e4Smiod
140*3d8817e4Smiod char *
bindtextdomain(domainname,dirname)141*3d8817e4Smiod bindtextdomain (domainname, dirname)
142*3d8817e4Smiod const char *domainname;
143*3d8817e4Smiod const char *dirname;
144*3d8817e4Smiod {
145*3d8817e4Smiod #if HAVE_SETENV || HAVE_PUTENV
146*3d8817e4Smiod char *old_val, *new_val, *cp;
147*3d8817e4Smiod size_t new_val_len;
148*3d8817e4Smiod
149*3d8817e4Smiod /* This does not make much sense here but to be compatible do it. */
150*3d8817e4Smiod if (domainname == NULL)
151*3d8817e4Smiod return NULL;
152*3d8817e4Smiod
153*3d8817e4Smiod /* Compute length of added path element. If we use setenv we don't need
154*3d8817e4Smiod the first byts for NLSPATH=, but why complicate the code for this
155*3d8817e4Smiod peanuts. */
156*3d8817e4Smiod new_val_len = sizeof ("NLSPATH=") - 1 + strlen (dirname)
157*3d8817e4Smiod + sizeof ("/%L/LC_MESSAGES/%N.cat");
158*3d8817e4Smiod
159*3d8817e4Smiod old_val = getenv ("NLSPATH");
160*3d8817e4Smiod if (old_val == NULL || old_val[0] == '\0')
161*3d8817e4Smiod {
162*3d8817e4Smiod old_val = NULL;
163*3d8817e4Smiod new_val_len += 1 + sizeof (LOCALEDIR) - 1
164*3d8817e4Smiod + sizeof ("/%L/LC_MESSAGES/%N.cat");
165*3d8817e4Smiod }
166*3d8817e4Smiod else
167*3d8817e4Smiod new_val_len += strlen (old_val);
168*3d8817e4Smiod
169*3d8817e4Smiod new_val = (char *) malloc (new_val_len);
170*3d8817e4Smiod if (new_val == NULL)
171*3d8817e4Smiod return NULL;
172*3d8817e4Smiod
173*3d8817e4Smiod # if HAVE_SETENV
174*3d8817e4Smiod cp = new_val;
175*3d8817e4Smiod # else
176*3d8817e4Smiod cp = stpcpy (new_val, "NLSPATH=");
177*3d8817e4Smiod # endif
178*3d8817e4Smiod
179*3d8817e4Smiod cp = stpcpy (cp, dirname);
180*3d8817e4Smiod cp = stpcpy (cp, "/%L/LC_MESSAGES/%N.cat:");
181*3d8817e4Smiod
182*3d8817e4Smiod if (old_val == NULL)
183*3d8817e4Smiod {
184*3d8817e4Smiod # if __STDC__
185*3d8817e4Smiod stpcpy (cp, LOCALEDIR "/%L/LC_MESSAGES/%N.cat");
186*3d8817e4Smiod # else
187*3d8817e4Smiod
188*3d8817e4Smiod cp = stpcpy (cp, LOCALEDIR);
189*3d8817e4Smiod stpcpy (cp, "/%L/LC_MESSAGES/%N.cat");
190*3d8817e4Smiod # endif
191*3d8817e4Smiod }
192*3d8817e4Smiod else
193*3d8817e4Smiod stpcpy (cp, old_val);
194*3d8817e4Smiod
195*3d8817e4Smiod # if HAVE_SETENV
196*3d8817e4Smiod setenv ("NLSPATH", new_val, 1);
197*3d8817e4Smiod free (new_val);
198*3d8817e4Smiod # else
199*3d8817e4Smiod putenv (new_val);
200*3d8817e4Smiod /* Do *not* free the environment entry we just entered. It is used
201*3d8817e4Smiod from now on. */
202*3d8817e4Smiod # endif
203*3d8817e4Smiod
204*3d8817e4Smiod #endif
205*3d8817e4Smiod
206*3d8817e4Smiod return (char *) domainname;
207*3d8817e4Smiod }
208*3d8817e4Smiod
209*3d8817e4Smiod #undef gettext
210*3d8817e4Smiod char *
gettext(msg)211*3d8817e4Smiod gettext (msg)
212*3d8817e4Smiod const char *msg;
213*3d8817e4Smiod {
214*3d8817e4Smiod int msgid;
215*3d8817e4Smiod
216*3d8817e4Smiod if (msg == NULL || catalog == (nl_catd) -1)
217*3d8817e4Smiod return (char *) msg;
218*3d8817e4Smiod
219*3d8817e4Smiod /* Get the message from the catalog. We always use set number 1.
220*3d8817e4Smiod The message ID is computed by the function `msg_to_cat_id'
221*3d8817e4Smiod which works on the table generated by `po-to-tbl'. */
222*3d8817e4Smiod msgid = msg_to_cat_id (msg);
223*3d8817e4Smiod if (msgid == -1)
224*3d8817e4Smiod return (char *) msg;
225*3d8817e4Smiod
226*3d8817e4Smiod return catgets (catalog, 1, msgid, (char *) msg);
227*3d8817e4Smiod }
228*3d8817e4Smiod
229*3d8817e4Smiod /* Look through the table `_msg_tbl' which has `_msg_tbl_length' entries
230*3d8817e4Smiod for the one equal to msg. If it is found return the ID. In case when
231*3d8817e4Smiod the string is not found return -1. */
232*3d8817e4Smiod static int
msg_to_cat_id(msg)233*3d8817e4Smiod msg_to_cat_id (msg)
234*3d8817e4Smiod const char *msg;
235*3d8817e4Smiod {
236*3d8817e4Smiod int cnt;
237*3d8817e4Smiod
238*3d8817e4Smiod for (cnt = 0; cnt < _msg_tbl_length; ++cnt)
239*3d8817e4Smiod if (strcmp (msg, _msg_tbl[cnt]._msg) == 0)
240*3d8817e4Smiod return _msg_tbl[cnt]._msg_number;
241*3d8817e4Smiod
242*3d8817e4Smiod return -1;
243*3d8817e4Smiod }
244*3d8817e4Smiod
245*3d8817e4Smiod
246*3d8817e4Smiod /* @@ begin of epilog @@ */
247*3d8817e4Smiod
248*3d8817e4Smiod /* We don't want libintl.a to depend on any other library. So we
249*3d8817e4Smiod avoid the non-standard function stpcpy. In GNU C Library this
250*3d8817e4Smiod function is available, though. Also allow the symbol HAVE_STPCPY
251*3d8817e4Smiod to be defined. */
252*3d8817e4Smiod #if !_LIBC && !HAVE_STPCPY
253*3d8817e4Smiod static char *
stpcpy(dest,src)254*3d8817e4Smiod stpcpy (dest, src)
255*3d8817e4Smiod char *dest;
256*3d8817e4Smiod const char *src;
257*3d8817e4Smiod {
258*3d8817e4Smiod while ((*dest++ = *src++) != '\0')
259*3d8817e4Smiod /* Do nothing. */ ;
260*3d8817e4Smiod return dest - 1;
261*3d8817e4Smiod }
262*3d8817e4Smiod #endif
263