8 #include "locale_impl.h"
21 static void *volatile bindings
;
23 static char *gettextdir(const char *domainname
, size_t *dirlen
)
26 for (p
=bindings
; p
; p
=p
->next
) {
27 if (!strcmp(p
->domainname
, domainname
) && p
->active
) {
29 return (char *)p
->dirname
;
35 char *bindtextdomain(const char *domainname
, const char *dirname
)
37 static volatile int lock
[2];
38 struct binding
*p
, *q
;
40 if (!domainname
) return 0;
41 if (!dirname
) return gettextdir(domainname
, &(size_t){0});
43 size_t domlen
= strlen(domainname
);
44 size_t dirlen
= strlen(dirname
);
45 if (domlen
> NAME_MAX
|| dirlen
>= PATH_MAX
) {
52 for (p
=bindings
; p
; p
=p
->next
) {
53 if (!strcmp(p
->domainname
, domainname
) &&
54 !strcmp(p
->dirname
, dirname
)) {
60 p
= calloc(sizeof *p
+ domlen
+ dirlen
+ 2, 1);
67 p
->domainname
= p
->buf
;
68 p
->dirname
= p
->buf
+ domlen
+ 1;
69 memcpy(p
->domainname
, domainname
, domlen
+1);
70 memcpy(p
->dirname
, dirname
, dirlen
+1);
71 a_cas_p(&bindings
, bindings
, p
);
74 a_store(&p
->active
, 1);
76 for (q
=bindings
; q
; q
=q
->next
) {
77 if (!strcmp(q
->domainname
, domainname
) && q
!= p
)
78 a_store(&q
->active
, 0);
83 return (char *)p
->dirname
;
86 static const char catnames
[][12] = {
95 static const char catlens
[] = { 8, 10, 7, 10, 11, 11 };
101 void *volatile plural_rule
;
102 volatile int nplurals
;
106 static char *dummy_gettextdomain()
111 weak_alias(dummy_gettextdomain
, __gettextdomain
);
113 const unsigned char *__map_file(const char *, size_t *);
114 int __munmap(void *, size_t);
115 unsigned long __pleval(const char *, unsigned long);
117 char *dcngettext(const char *domainname
, const char *msgid1
, const char *msgid2
, unsigned long int n
, int category
)
119 static struct msgcat
*volatile cats
;
121 struct __locale_struct
*loc
= CURRENT_LOCALE
;
122 const struct __locale_map
*lm
;
123 const char *dirname
, *locname
, *catname
;
124 size_t dirlen
, loclen
, catlen
, domlen
;
126 if ((unsigned)category
>= LC_ALL
) goto notrans
;
128 if (!domainname
) domainname
= __gettextdomain();
130 domlen
= strlen(domainname
);
131 if (domlen
> NAME_MAX
) goto notrans
;
133 dirname
= gettextdir(domainname
, &dirlen
);
134 if (!dirname
) goto notrans
;
136 lm
= loc
->cat
[category
];
139 return (char *) ((n
== 1) ? msgid1
: msgid2
);
143 catname
= catnames
[category
];
144 catlen
= catlens
[category
];
145 loclen
= strlen(locname
);
147 size_t namelen
= dirlen
+1 + loclen
+1 + catlen
+1 + domlen
+3;
148 char name
[namelen
+1], *s
= name
;
150 memcpy(s
, dirname
, dirlen
);
153 memcpy(s
, locname
, loclen
);
156 memcpy(s
, catname
, catlen
);
159 memcpy(s
, domainname
, domlen
);
165 for (p
=cats
; p
; p
=p
->next
)
166 if (!strcmp(p
->name
, name
))
172 const void *map
= __map_file(name
, &map_size
);
173 if (!map
) goto notrans
;
174 p
= calloc(sizeof *p
+ namelen
+ 1, 1);
176 __munmap((void *)map
, map_size
);
180 p
->map_size
= map_size
;
181 memcpy(p
->name
, name
, namelen
+1);
185 } while (a_cas_p(&cats
, old_cats
, p
) != old_cats
);
188 const char *trans
= __mo_lookup(p
->map
, p
->map_size
, msgid1
);
189 if (!trans
) goto notrans
;
191 /* Non-plural-processing gettext forms pass a null pointer as
192 * msgid2 to request that dcngettext suppress plural processing. */
193 if (!msgid2
) return (char *)trans
;
195 if (!p
->plural_rule
) {
196 const char *rule
= "n!=1;";
197 unsigned long np
= 2;
198 const char *r
= __mo_lookup(p
->map
, p
->map_size
, "");
200 while (r
&& strncmp(r
, "Plural-Forms:", 13)) {
206 while (isspace(*r
)) r
++;
207 if (!strncmp(r
, "nplurals=", 9)) {
208 np
= strtoul(r
+9, &z
, 10);
211 while (*r
&& *r
!= ';') r
++;
214 while (isspace(*r
)) r
++;
215 if (!strncmp(r
, "plural=", 7))
219 a_store(&p
->nplurals
, np
);
220 a_cas_p(&p
->plural_rule
, 0, (void *)rule
);
223 unsigned long plural
= __pleval(p
->plural_rule
, n
);
224 if (plural
> p
->nplurals
) goto notrans
;
226 size_t rem
= p
->map_size
- (trans
- (char *)p
->map
);
227 size_t l
= strnlen(trans
, rem
);
233 return (char *)trans
;
236 char *dcgettext(const char *domainname
, const char *msgid
, int category
)
238 return dcngettext(domainname
, msgid
, 0, 1, category
);
241 char *dngettext(const char *domainname
, const char *msgid1
, const char *msgid2
, unsigned long int n
)
243 return dcngettext(domainname
, msgid1
, msgid2
, n
, LC_MESSAGES
);
246 char *dgettext(const char *domainname
, const char *msgid
)
248 return dcngettext(domainname
, msgid
, 0, 1, LC_MESSAGES
);