7 #include "locale_impl.h"
20 static void *volatile bindings;
22 static char *gettextdir(const char *domainname, size_t *dirlen)
25 for (p=bindings; p; p=p->next) {
26 if (!strcmp(p->domainname, domainname) && p->active) {
28 return (char *)p->dirname;
34 char *bindtextdomain(const char *domainname, const char *dirname)
37 struct binding *p, *q;
39 if (!domainname) return 0;
40 if (!dirname) return gettextdir(domainname, &(size_t){0});
42 size_t domlen = strlen(domainname);
43 size_t dirlen = strlen(dirname);
44 if (domlen > NAME_MAX || dirlen >= PATH_MAX) {
51 for (p=bindings; p; p=p->next) {
52 if (!strcmp(p->domainname, domainname) &&
53 !strcmp(p->dirname, dirname)) {
59 p = malloc(sizeof *p + domlen + dirlen + 2);
66 p->domainname = p->buf;
67 p->dirname = p->buf + domlen + 1;
68 memcpy(p->domainname, domainname, domlen+1);
69 memcpy(p->dirname, dirname, dirlen+1);
70 a_cas_p(&bindings, bindings, p);
73 a_store(&p->active, 1);
75 for (q=bindings; q; q=q->next) {
76 if (!strcmp(p->domainname, domainname) && q != p)
77 a_store(&q->active, 0);
82 return (char *)p->dirname;
85 static const char catnames[][12] = {
92 static const char catlens[] = { 7, 10, 11, 11 };
101 static char *dummy_gettextdomain()
106 weak_alias(dummy_gettextdomain, __gettextdomain);
108 const unsigned char *__map_file(const char *, size_t *);
109 int __munmap(void *, size_t);
111 char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long int n, int category)
113 static struct msgcat *volatile cats;
115 struct __locale_struct *loc = CURRENT_LOCALE;
116 struct __locale_map *lm;
117 const char *dirname, *locname, *catname;
118 size_t dirlen, loclen, catlen, domlen;
120 if (!domainname) domainname = __gettextdomain();
122 domlen = strlen(domainname);
123 if (domlen > NAME_MAX) goto notrans;
125 dirname = gettextdir(domainname, &dirlen);
126 if (!dirname) goto notrans;
130 locname = loc->messages_name;
131 if (!*locname) goto notrans;
136 lm = loc->cat[category-2];
137 if (!lm) goto notrans;
142 return (char *) ((n == 1) ? msgid1 : msgid2);
145 catname = catnames[category-2];
146 catlen = catlens[category-2];
147 loclen = strlen(locname);
149 size_t namelen = dirlen+1 + loclen+1 + catlen+1 + domlen+3;
150 char name[namelen+1], *s = name;
152 memcpy(s, dirname, dirlen);
155 memcpy(s, locname, loclen);
158 memcpy(s, catname, catlen);
161 memcpy(s, domainname, domlen);
167 for (p=cats; p; p=p->next)
168 if (!strcmp(p->name, name))
174 const void *map = __map_file(name, &map_size);
175 if (!map) goto notrans;
176 p = malloc(sizeof *p + namelen + 1);
178 __munmap((void *)map, map_size);
182 p->map_size = map_size;
183 memcpy(p->name, name, namelen+1);
187 } while (a_cas_p(&cats, old_cats, p) != old_cats);
190 const char *trans = __mo_lookup(p->map, p->map_size, msgid1);
191 if (!trans) goto notrans;
193 /* FIXME: support alternate plural rules */
195 size_t l = strlen(trans);
196 if (l+1 >= p->map_size - (trans - (char *)p->map))
200 return (char *)trans;
203 char *dcgettext(const char *domainname, const char *msgid, int category)
205 return dcngettext(domainname, msgid, msgid, 1, category);
208 char *dngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long int n)
210 return dcngettext(domainname, msgid1, msgid2, n, LC_MESSAGES);
213 char *dgettext(const char *domainname, const char *msgid)
215 return dcngettext(domainname, msgid, msgid, 1, LC_MESSAGES);