1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
19 This must come before <config.h> because <config.h> may include
20 <features.h>, and once <features.h> has been included, it's too late. */
29 #include <sys/types.h>
31 #if defined HAVE_ALLOCA_H
38 void *alloca(size_t size
);
53 #if defined HAVE_UNISTD_H
57 #if defined HAVE_SYS_PARAM_H
58 #include <sys/param.h>
62 #include <malloc.h> /* Needed for alloca() on MingW/Win32 */
67 #include "intl/gettext/gettextP.h"
68 #include "intl/gettext/libintl.h"
69 #include "intl/gettext/hash-string.h"
70 #include "util/string.h"
72 /* Amount to increase buffer size by in each try. */
75 /* The following is from pathmax.h. */
76 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
77 PATH_MAX but might cause redefinition warnings when sys/param.h is
78 later included (as on MORE/BSD 4.3). */
79 #if defined _POSIX_VERSION || defined HAVE_LIMITS_H
83 #ifndef _POSIX_PATH_MAX
84 #define _POSIX_PATH_MAX 255
87 #if !defined PATH_MAX && defined _PC_PATH_MAX
88 #define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
91 /* Don't include sys/param.h if it already has been. */
92 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
93 #include <sys/param.h>
96 #if !defined PATH_MAX && defined MAXPATHLEN
97 #define PATH_MAX MAXPATHLEN
101 #define PATH_MAX _POSIX_PATH_MAX
105 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
106 it may be concatenated to a directory pathname.
107 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
109 #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
110 /* Win32, OS/2, DOS */
111 #define HAS_DEVICE(P) (isasciialpha((P)[0]) && (P)[1] == ':')
112 #define IS_ABSOLUTE_PATH(P) (dir_sep((P)[0]) || HAS_DEVICE (P))
113 #define IS_PATH_WITH_DIR(P) (strchr (P, '/') || strchr (P, '\\') || HAS_DEVICE (P))
116 #define IS_ABSOLUTE_PATH(P) dir_sep((P)[0])
117 #define IS_PATH_WITH_DIR(P) strchr (P, '/')
120 /* XPG3 defines the result of `setlocale (category, NULL)' as:
121 ``Directs `setlocale()' to query `category' and return the current
122 setting of `local'.''
123 However it does not specify the exact format. Neither do SUSV2 and
124 ISO C 99. So we can use this feature only on selected systems (e.g.
125 those using GNU C Library). */
126 #if (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
127 #define HAVE_LOCALE_NULL
130 /* This is the type used for the search tree where known translations
132 struct known_translation_t
{
133 /* Domain in which to search. */
134 unsigned char *domainname
;
139 /* State of the catalog counter at the point the string was found. */
142 /* Catalog where the string was found. */
143 struct loaded_l10nfile
*domain
;
145 /* And finally the translation. */
146 const unsigned char *translation
;
147 size_t translation_length
;
149 /* Pointer to the string in question. */
150 unsigned char msgid
[1];
153 /* Root of the search tree with known translations. We can use this
154 only if the system provides the `tsearch' function family. */
155 #if defined HAVE_TSEARCH
160 /* Function to compare two entries in the table of known translations. */
161 static int transcmp(const void *p1
, const void *p2
);
165 transcmp(const void *p1
, const void *p2
)
167 const struct known_translation_t
*s1
;
168 const struct known_translation_t
*s2
;
171 s1
= (const struct known_translation_t
*) p1
;
172 s2
= (const struct known_translation_t
*) p2
;
174 result
= strcmp(s1
->msgid
, s2
->msgid
);
176 result
= strcmp(s1
->domainname
, s2
->domainname
);
178 /* We compare the category last (though this is the cheapest
179 operation) since it is hopefully always the same (namely
181 result
= s1
->category
- s2
->category
;
188 /* Name of the default domain used for gettext(3) prior any call to
189 textdomain(3). The default value for this is "messages". */
190 const unsigned char _nl_default_default_domain__
[] = "messages";
192 /* Value used as the default domain for gettext(3). */
193 const unsigned char *_nl_current_default_domain__
= _nl_default_default_domain__
;
195 /* Contains the default location of the message catalogs. */
196 const unsigned char _nl_default_dirname__
[] = LOCALEDIR
;
198 /* Contains application-specific LANGUAGE variation, taking precedence to the
199 * $LANGUAGE environment variable. */
200 unsigned char *LANGUAGE
= NULL
;
202 /* List with bindings of specific domains created by bindtextdomain()
204 struct binding
*_nl_domain_bindings__
;
206 /* Prototypes for local functions. */
207 static unsigned char *plural_lookup(struct loaded_l10nfile
* domain
,
209 const unsigned char *translation
,
210 size_t translation_len
);
211 static unsigned long int plural_eval(struct expression
* pexp
,
212 unsigned long int n
);
213 static const unsigned char *category_to_name(int category
);
214 static const unsigned char *guess_category_value(int category
,
215 const unsigned char *categoryname
);
217 /* For those loosing systems which don't have `alloca' we have to add
218 some additional code emulating it. */
220 /* Nothing has to be done. */
221 #define ADD_BLOCK(list, address) /* nothing */
222 #define FREE_BLOCKS(list) /* nothing */
226 struct block_list
*next
;
228 #define ADD_BLOCK(list, addr) \
230 struct block_list *newp = (struct block_list *) malloc(sizeof(*newp)); \
231 /* If we cannot get a free block we cannot add the new element to \
233 if (newp != NULL) { \
234 newp->address = (addr); \
235 newp->next = (list); \
239 #define FREE_BLOCKS(list) \
241 while (list != NULL) { \
242 struct block_list *old = list; \
244 free (old->address); \
249 #define alloca(size) (malloc (size))
250 #endif /* have alloca */
252 typedef unsigned char transmem_block_t
;
254 /* Checking whether the binaries runs SUID must be done and glibc provides
255 easier methods therefore we make a difference here. */
265 #define geteuid() getuid()
269 #define getegid() getgid()
272 static int enable_secure
;
274 #define ENABLE_SECURE (enable_secure == 1)
275 #define DETERMINE_SECURE \
276 if (enable_secure == 0) \
278 if (getuid () != geteuid () || getgid () != getegid ()) \
281 enable_secure = -1; \
284 /* Look up MSGID in the DOMAINNAME message catalog for the current
285 CATEGORY locale and, if PLURAL is nonzero, search over string
286 depending on the plural form determined by N. */
288 dcigettext__(const unsigned char *domainname
, const unsigned char *msgid1
, const unsigned char *msgid2
,
289 int plural
, unsigned long int n
, int category
)
292 struct block_list
*block_list
= NULL
;
294 struct loaded_l10nfile
*domain
;
295 struct binding
*binding
;
296 const unsigned char *categoryname
;
297 const unsigned char *categoryvalue
;
298 unsigned char *dirname
, *xdomainname
;
299 unsigned char *single_locale
;
300 unsigned char *retval
;
304 #if defined HAVE_TSEARCH
305 struct known_translation_t
*search
;
306 struct known_translation_t
**foundp
= NULL
;
309 size_t domainname_len
;
311 /* If no real MSGID is given return NULL. */
315 /* If DOMAINNAME is NULL, we are interested in the default domain. If
316 CATEGORY is not LC_MESSAGES this might not make much sense but the
317 definition left this undefined. */
318 if (domainname
== NULL
)
319 domainname
= _nl_current_default_domain__
;
321 #if defined HAVE_TSEARCH
322 msgid_len
= strlen(msgid1
) + 1;
324 /* Try to find the translation among those which we found at
326 search
= (struct known_translation_t
*)
327 alloca(offsetof(struct known_translation_t
, msgid
) + msgid_len
);
329 memcpy(search
->msgid
, msgid1
, msgid_len
);
330 search
->domainname
= (unsigned char *) domainname
;
331 search
->category
= category
;
333 foundp
= (struct known_translation_t
**) tfind(search
, &root
, transcmp
);
334 if (foundp
!= NULL
&& (*foundp
)->counter
== _nl_msg_cat_cntr
) {
335 /* Now deal with plural. */
337 retval
= plural_lookup((*foundp
)->domain
, n
,
338 (*foundp
)->translation
,
339 (*foundp
)->translation_length
);
341 retval
= (unsigned char *) (*foundp
)->translation
;
347 /* Preserve the `errno' value. */
350 /* See whether this is a SUID binary or not. */
353 /* First find matching binding. */
354 for (binding
= _nl_domain_bindings__
; binding
!= NULL
;
355 binding
= binding
->next
) {
356 int compare
= strcmp(domainname
, binding
->domainname
);
362 /* It is not in the list. */
369 dirname
= (unsigned char *) _nl_default_dirname__
;
370 else if (IS_ABSOLUTE_PATH(binding
->dirname
))
371 dirname
= binding
->dirname
;
373 /* We have a relative path. Make it absolute now. */
374 size_t dirname_len
= strlen(binding
->dirname
) + 1;
378 path_max
= (unsigned int) PATH_MAX
;
379 path_max
+= 2; /* The getcwd docs say to do this. */
382 dirname
= (unsigned char *) alloca(path_max
+ dirname_len
);
383 ADD_BLOCK(block_list
, dirname
);
386 ret
= getcwd(dirname
, path_max
);
387 if (ret
!= NULL
|| errno
!= ERANGE
)
390 path_max
+= path_max
/ 2;
391 path_max
+= PATH_INCR
;
395 /* We cannot get the current working directory. Don't signal an
396 error but simply return the default string. */
397 FREE_BLOCKS(block_list
);
399 return (plural
== 0 ? (unsigned char *) msgid1
400 /* Use the Germanic plural rule. */
401 : n
== 1 ? (unsigned char *) msgid1
: (unsigned char *) msgid2
);
404 stpcpy(stpcpy(strchr(dirname
, '\0'), "/"), binding
->dirname
);
407 /* Now determine the symbolic name of CATEGORY and its value. */
408 categoryname
= category_to_name(category
);
409 categoryvalue
= guess_category_value(category
, categoryname
);
411 domainname_len
= strlen(domainname
);
412 xdomainname
= (unsigned char *) alloca(strlen(categoryname
)
413 + domainname_len
+ 5);
414 ADD_BLOCK(block_list
, xdomainname
);
416 stpcpy(mempcpy(stpcpy(stpcpy(xdomainname
, categoryname
), "/"),
417 domainname
, domainname_len
), ".mo");
419 /* Creating working area. */
420 single_locale
= (unsigned char *) alloca(strlen(categoryvalue
) + 1);
421 ADD_BLOCK(block_list
, single_locale
);
423 /* Search for the given string. This is a loop because we perhaps
424 got an ordered list of languages to consider for the translation. */
426 /* Make CATEGORYVALUE point to the next element of the list. */
427 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
429 if (categoryvalue
[0] == '\0') {
430 /* The whole contents of CATEGORYVALUE has been searched but
431 no valid entry has been found. We solve this situation
432 by implicitly appending a "C" entry, i.e. no translation
434 single_locale
[0] = 'C';
435 single_locale
[1] = '\0';
437 unsigned char *cp
= single_locale
;
439 while (categoryvalue
[0] != '\0'
440 && categoryvalue
[0] != ':')
441 *cp
++ = *categoryvalue
++;
444 /* When this is a SUID binary we must not allow accessing files
445 outside the dedicated directories. */
446 if (ENABLE_SECURE
&& IS_PATH_WITH_DIR(single_locale
))
447 /* Ingore this entry. */
451 /* If the current locale value is C (or POSIX) we don't load a
452 domain. Return the MSGID. */
453 if (strcmp(single_locale
, "C") == 0
454 || strcmp(single_locale
, "POSIX") == 0) {
455 FREE_BLOCKS(block_list
);
457 return (plural
== 0 ? (unsigned char *) msgid1
458 /* Use the Germanic plural rule. */
459 : n
== 1 ? (unsigned char *) msgid1
: (unsigned char *) msgid2
);
462 /* Find structure describing the message catalog matching the
463 DOMAINNAME and CATEGORY. */
464 domain
= _nl_find_domain(dirname
, single_locale
, xdomainname
,
467 if (domain
!= NULL
) {
468 retval
= _nl_find_msg(domain
, binding
, msgid1
, &retlen
);
470 if (retval
== NULL
) {
473 for (cnt
= 0; domain
->successor
[cnt
] != NULL
;
475 retval
= _nl_find_msg(domain
->
480 if (retval
!= NULL
) {
481 domain
= domain
->successor
[cnt
];
487 if (retval
!= NULL
) {
488 /* Found the translation of MSGID1 in domain DOMAIN:
489 starting at RETVAL, RETLEN bytes. */
490 FREE_BLOCKS(block_list
);
492 #if defined HAVE_TSEARCH
493 if (foundp
== NULL
) {
494 /* Create a new entry and add it to the search tree. */
495 struct known_translation_t
*newp
;
497 newp
= (struct known_translation_t
*)
509 memcpy(newp
->domainname
,
512 newp
->category
= category
;
515 newp
->domain
= domain
;
516 newp
->translation
= retval
;
517 newp
->translation_length
=
520 /* Insert the entry in the search tree. */
528 /* The insert failed. */
532 /* We can update the existing entry. */
533 (*foundp
)->counter
= _nl_msg_cat_cntr
;
534 (*foundp
)->domain
= domain
;
535 (*foundp
)->translation
= retval
;
536 (*foundp
)->translation_length
= retlen
;
539 /* Now deal with plural. */
541 retval
= plural_lookup(domain
, n
,
552 _nl_find_msg(struct loaded_l10nfile
*domain_file
,
553 struct binding
*domainbinding
,
554 const unsigned char *msgid
, size_t *lengthp
)
556 struct loaded_domain
*domain
;
558 unsigned char *result
;
561 if (domain_file
->decided
== 0)
562 _nl_load_domain(domain_file
, domainbinding
);
564 if (domain_file
->data
== NULL
)
567 domain
= (struct loaded_domain
*) domain_file
->data
;
569 /* Locate the MSGID and its translation. */
570 if (domain
->hash_size
> 2 && domain
->hash_tab
!= NULL
) {
571 /* Use the hashing table. */
572 nls_uint32 len
= strlen(msgid
);
573 nls_uint32 hash_val
= hash_string(msgid
);
574 nls_uint32 idx
= hash_val
% domain
->hash_size
;
575 nls_uint32 incr
= 1 + (hash_val
% (domain
->hash_size
- 2));
579 W(domain
->must_swap
, domain
->hash_tab
[idx
]);
582 /* Hash table entry is empty. */
585 /* Compare msgid with the original string at index nstr-1.
586 We compare the lengths with >=, not ==, because plural entries
587 are represented by strings with an embedded NUL. */
590 domain
->orig_tab
[nstr
- 1].length
) >= len
594 domain
->data
+ W(domain
->must_swap
,
595 domain
->orig_tab
[nstr
-
602 if (idx
>= domain
->hash_size
- incr
)
603 idx
-= domain
->hash_size
- incr
;
609 /* Try the default method: binary search in the sorted array of
614 top
= domain
->nstrings
;
615 while (bottom
< top
) {
618 act
= (bottom
+ top
) / 2;
619 cmp_val
= strcmp(msgid
, (domain
->data
620 + W(domain
->must_swap
,
621 domain
->orig_tab
[act
].
625 else if (cmp_val
> 0)
630 /* No translation was found. */
635 /* The translation was found at index ACT. If we have to convert the
636 string to use a different character set, this is the time. */
637 result
= ((unsigned char *) domain
->data
638 + W(domain
->must_swap
, domain
->trans_tab
[act
].offset
));
639 resultlen
= W(domain
->must_swap
, domain
->trans_tab
[act
].length
) + 1;
642 if (domain
->codeset_cntr
643 != (domainbinding
!= NULL
? domainbinding
->codeset_cntr
: 0)) {
644 /* The domain's codeset has changed through bind_textdomain_codeset()
645 since the message catalog was initialized or last accessed. We
646 have to reinitialize the converter. */
647 _nl_free_domain_conv(domain
);
648 _nl_init_domain_conv(domain_file
, domain
, domainbinding
);
651 if (domain
->conv
!= (iconv_t
) - 1) {
652 /* We are supposed to do a conversion. First allocate an
653 appropriate table with the same structure as the table
654 of translations in the file, where we can put the pointers
655 to the converted strings in.
656 There is a slight complication with plural entries. They
657 are represented by consecutive NUL terminated strings. We
658 handle this case by converting RESULTLEN bytes, including
661 if (domain
->conv_tab
== NULL
662 && ((domain
->conv_tab
= (unsigned char **) calloc(domain
->nstrings
,
663 sizeof(unsigned char *)))
665 /* Mark that we didn't succeed allocating a table. */
666 domain
->conv_tab
= (unsigned char **) -1;
668 if (domain
->conv_tab
== (unsigned char **) -1)
669 /* Nothing we can do, no more memory. */
672 if (domain
->conv_tab
[act
] == NULL
) {
673 /* We haven't used this string so far, so it is not
674 translated yet. Do this now. */
675 /* We use a bit more efficient memory handling.
676 We allocate always larger blocks which get used over
677 time. This is faster than many small allocations. */
678 #define INITIAL_BLOCK_SIZE 4080
679 static unsigned char *freemem
;
680 static size_t freemem_size
;
682 const unsigned char *inbuf
;
683 unsigned char *outbuf
;
685 transmem_block_t
*transmem_list
= NULL
;
687 inbuf
= (const unsigned char *) result
;
688 outbuf
= freemem
+ sizeof(size_t);
692 transmem_block_t
*newmem
;
693 ICONV_CONST
char *inptr
= (ICONV_CONST
char *) inbuf
;
694 size_t inleft
= resultlen
;
695 char *outptr
= (unsigned char *) outbuf
;
698 if (freemem_size
< sizeof(size_t))
701 outleft
= freemem_size
- sizeof(size_t);
702 if (iconv(domain
->conv
, &inptr
, &inleft
,
705 outbuf
= (unsigned char *) outptr
;
708 if (errno
!= E2BIG
) {
713 /* We must allocate a new buffer or resize the old one. */
714 if (malloc_count
> 0) {
719 newmem
= (transmem_block_t
*)
720 realloc(transmem_list
,
724 freemem_size
= INITIAL_BLOCK_SIZE
;
725 newmem
= (transmem_block_t
*)
726 malloc(freemem_size
);
728 if (newmem
== NULL
) {
733 transmem_list
= newmem
;
735 outbuf
= freemem
+ sizeof(size_t);
738 /* We have now in our buffer a converted string. Put this
739 into the table of conversions. */
740 *(size_t *) freemem
= outbuf
- freemem
- sizeof(size_t);
741 domain
->conv_tab
[act
] = (unsigned char *) freemem
;
742 /* Shrink freemem, but keep it aligned. */
743 freemem_size
-= outbuf
- freemem
;
745 freemem
+= freemem_size
& (alignof(size_t) - 1);
746 freemem_size
= freemem_size
& ~(alignof(size_t) - 1);
750 /* Now domain->conv_tab[act] contains the translation of all
751 the plural variants. */
752 result
= domain
->conv_tab
[act
] + sizeof(size_t);
753 resultlen
= *(size_t *) domain
->conv_tab
[act
];
757 /* The result string is converted. */
759 #endif /* HAVE_ICONV */
761 *lengthp
= resultlen
;
765 /* Look up a plural variant. */
766 static unsigned char *
767 plural_lookup(struct loaded_l10nfile
*domain
, unsigned long int n
,
768 const unsigned char *translation
, size_t translation_len
)
770 struct loaded_domain
*domaindata
=
771 (struct loaded_domain
*) domain
->data
;
772 unsigned long int indexx
;
773 const unsigned char *p
;
775 indexx
= plural_eval(domaindata
->plural
, n
);
776 if (indexx
>= domaindata
->nplurals
)
777 /* This should never happen. It means the plural expression and the
778 given maximum value do not match. */
781 /* Skip INDEX strings at TRANSLATION. */
783 while (indexx
-- > 0) {
786 /* And skip over the NUL byte. */
789 if (p
>= translation
+ translation_len
)
790 /* This should never happen. It means the plural expression
791 evaluated to a value larger than the number of variants
792 available for MSGID1. */
793 return (unsigned char *) translation
;
795 return (unsigned char *) p
;
798 /* Function to evaluate the plural expression and return an index value. */
799 static unsigned long int
800 plural_eval(struct expression
*pexp
, unsigned long int n
)
802 switch (pexp
->nargs
) {
804 switch (pexp
->operation
) {
808 return pexp
->val
.num
;
816 /* pexp->operation must be lnot. */
817 unsigned long int arg
=
818 plural_eval(pexp
->val
.args
[0], n
);
823 unsigned long int leftarg
=
824 plural_eval(pexp
->val
.args
[0], n
);
825 if (pexp
->operation
== lor
)
827 || plural_eval(pexp
->val
.
829 else if (pexp
->operation
== land
)
831 && plural_eval(pexp
->val
.
834 unsigned long int rightarg
=
835 plural_eval(pexp
->val
.args
[1],
838 switch (pexp
->operation
) {
863 case greater_or_equal
:
881 /* pexp->operation must be qmop. */
882 unsigned long int boolarg
=
883 plural_eval(pexp
->val
.args
[0], n
);
884 return plural_eval(pexp
->val
.
885 args
[boolarg
? 1 : 2], n
);
892 /* Return string representation of locale CATEGORY. */
893 static const unsigned char *
894 category_to_name(int category
)
896 const unsigned char *retval
;
901 retval
= "LC_COLLATE";
911 retval
= "LC_MONETARY";
916 retval
= "LC_NUMERIC";
926 retval
= "LC_MESSAGES";
931 retval
= "LC_RESPONSE";
936 /* This might not make sense but is perhaps better than any other
942 /* If you have a better idea for a default value let me know. */
949 /* Guess value of current locale from value of the environment variables. */
950 static const unsigned char *
951 guess_category_value(int category
, const unsigned char *categoryname
)
953 const unsigned char *language
;
954 const unsigned char *retval
;
956 /* Takes precedence to anything else, damn it's what the application wants!
958 if (LANGUAGE
&& *LANGUAGE
)
961 /* The highest priority value is the `LANGUAGE' environment
962 variable. But we don't use the value if the currently selected
963 locale is the C locale. This is a GNU extension. */
964 /* XXX: This GNU extension breaks things for me and I can't see what is it
965 * good for - I think it only makes things more difficult and arcane, since
966 * it requires you to set up more variables than LANGUAGE, it's poorly
967 * documented and so on. If this breaks anything, let me know at
968 * pasky@ucw.cz, I'm really curious. If LANGUAGE exists, we just use it and
969 * do no more tests. This is an ELinks extension. --pasky */
970 language
= getenv("LANGUAGE");
971 if (language
&& language
[0])
974 /* We have to proceed with the POSIX methods of looking to `LC_ALL',
975 `LC_xxx', and `LANG'. On some systems this can be done by the
976 `setlocale' function itself. */
977 #if (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
978 retval
= setlocale(category
, NULL
);
980 /* Setting of LC_ALL overwrites all other. */
981 retval
= getenv("LC_ALL");
982 if (retval
== NULL
|| retval
[0] == '\0') {
983 /* Next comes the name of the desired category. */
984 retval
= getenv(categoryname
);
985 if (retval
== NULL
|| retval
[0] == '\0') {
986 /* Last possibility is the LANG environment variable. */
987 retval
= getenv("LANG");
988 if (retval
== NULL
|| retval
[0] == '\0')
989 /* We use C as the default domain. POSIX says this is
990 implementation defined. */