Module Name: src Committed By: christos Date: Fri May 29 12:26:28 UTC 2015
Modified Files: src/lib/libintl: gettext.c libintl.h textdomain.c Log Message: Patch from William Orr in tech-userlevel: - Added most *p*gettext functions - Added basic function to concat msgctxt and msgid - Simplify free handling Need to write tests. To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/lib/libintl/gettext.c cvs rdiff -u -r1.4 -r1.5 src/lib/libintl/libintl.h cvs rdiff -u -r1.13 -r1.14 src/lib/libintl/textdomain.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libintl/gettext.c diff -u src/lib/libintl/gettext.c:1.28 src/lib/libintl/gettext.c:1.29 --- src/lib/libintl/gettext.c:1.28 Mon Jul 30 19:04:42 2012 +++ src/lib/libintl/gettext.c Fri May 29 08:26:28 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: gettext.c,v 1.28 2012/07/30 23:04:42 yamt Exp $ */ +/* $NetBSD: gettext.c,v 1.29 2015/05/29 12:26:28 christos Exp $ */ /*- * Copyright (c) 2000, 2001 Citrus Project, @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: gettext.c,v 1.28 2012/07/30 23:04:42 yamt Exp $"); +__RCSID("$NetBSD: gettext.c,v 1.29 2015/05/29 12:26:28 christos Exp $"); #include <sys/param.h> #include <sys/stat.h> @@ -51,6 +51,16 @@ __RCSID("$NetBSD: gettext.c,v 1.28 2012/ #include "plural_parser.h" #include "pathnames.h" +/* GNU gettext added a hack to add some context to messages. If a message is + * used in multiple locations, it needs some amount of context to make the + * translation clear to translators. GNU gettext, rather than modifying the + * message format, concatenates the context, \004 and the message id. + */ +#define MSGCTXT_ID_SEPARATOR '\004' + +static const char *pgettext_impl(const char *, const char *, const char *, + const char *, unsigned long int, int); +static char *concatenate_ctxt_id(const char *, const char *); static const char *lookup_category(int); static const char *split_locale(const char *); static const char *lookup_mofile(char *, size_t, const char *, const char *, @@ -105,6 +115,73 @@ dngettext(const char *domainname, const return dcngettext(domainname, msgid1, msgid2, n, LC_MESSAGES); } +const char * +pgettext(const char *msgctxt, const char *msgid) +{ + + return pgettext_impl(NULL, msgctxt, msgid, NULL, 1UL, LC_MESSAGES); +} + +const char * +dpgettext(const char *domainname, const char *msgctxt, const char *msgid) +{ + + return pgettext_impl(domainname, msgctxt, msgid, NULL, 1UL, LC_MESSAGES); +} + +const char * +dcpgettext(const char *domainname, const char *msgctxt, const char *msgid, + int category) +{ + + return pgettext_impl(domainname, msgctxt, msgid, NULL, 1UL, category); +} + +const char * +npgettext(const char *msgctxt, const char *msgid1, const char *msgid2, + unsigned long int n) +{ + + return pgettext_impl(NULL, msgctxt, msgid1, msgid2, n, LC_MESSAGES); +} + +const char * +dnpgettext(const char *domainname, const char *msgctxt, const char *msgid1, + const char *msgid2, unsigned long int n) +{ + + return pgettext_impl(domainname, msgctxt, msgid1, msgid2, n, LC_MESSAGES); +} + +const char * +dcnpgettext(const char *domainname, const char *msgctxt, const char *msgid1, + const char *msgid2, unsigned long int n, int category) +{ + + return pgettext_impl(domainname, msgctxt, msgid1, msgid2, n, category); +} + +static const char * +pgettext_impl(const char *domainname, const char *msgctxt, const char *msgid1, + const char *msgid2, unsigned long int n, int category) +{ + char *msgctxt_id; + char *translation; + char *p; + + if ((msgctxt_id = concatenate_ctxt_id(msgctxt, msgid1)) == NULL) + return msgid1; + + translation = dcngettext(domainname, msgctxt_id, + msgid2, n, category); + free(msgctxt_id); + + p = strchr(translation, '\004'); + if (p) + return p + 1; + return translation; +} + /* * dcngettext() - * lookup internationalized message on database locale/category/domainname @@ -126,6 +203,17 @@ dngettext(const char *domainname, const * /usr/share/locale! (or we should move those files into /usr/libdata) */ +static char * +concatenate_ctxt_id(const char *msgctxt, const char *msgid) +{ + char *ret; + + if (asprintf(&ret, "%s%c%s", msgctxt, MSGCTXT_ID_SEPARATOR, msgid) == -1) + return NULL; + + return ret; +} + static const char * lookup_category(int category) { @@ -659,12 +747,13 @@ fail: static void free_sysdep_table(struct mosysdepstr_h **table, uint32_t nstring) { - uint32_t i; - for (i=0; i<nstring; i++) { + if (! table) + return; + + for (uint32_t i = 0; i < nstring; i++) { if (table[i]) { - if (table[i]->expanded) - free(table[i]->expanded); + free(table[i]->expanded); free(table[i]); } } @@ -680,26 +769,16 @@ unmapit(struct domainbinding *db) if (mohandle->addr && mohandle->addr != MAP_FAILED) munmap(mohandle->addr, mohandle->len); mohandle->addr = NULL; - if (mohandle->mo.mo_otable) - free(mohandle->mo.mo_otable); - if (mohandle->mo.mo_ttable) - free(mohandle->mo.mo_ttable); - if (mohandle->mo.mo_charset) - free(mohandle->mo.mo_charset); - if (mohandle->mo.mo_htable) - free(mohandle->mo.mo_htable); - if (mohandle->mo.mo_sysdep_segs) - free(mohandle->mo.mo_sysdep_segs); - if (mohandle->mo.mo_sysdep_otable) { - free_sysdep_table(mohandle->mo.mo_sysdep_otable, - mohandle->mo.mo_sysdep_nstring); - } - if (mohandle->mo.mo_sysdep_ttable) { - free_sysdep_table(mohandle->mo.mo_sysdep_ttable, - mohandle->mo.mo_sysdep_nstring); - } - if (mohandle->mo.mo_plural) - _gettext_free_plural(mohandle->mo.mo_plural); + free(mohandle->mo.mo_otable); + free(mohandle->mo.mo_ttable); + free(mohandle->mo.mo_charset); + free(mohandle->mo.mo_htable); + free(mohandle->mo.mo_sysdep_segs); + free_sysdep_table(mohandle->mo.mo_sysdep_otable, + mohandle->mo.mo_sysdep_nstring); + free_sysdep_table(mohandle->mo.mo_sysdep_ttable, + mohandle->mo.mo_sysdep_nstring); + _gettext_free_plural(mohandle->mo.mo_plural); memset(&mohandle->mo, 0, sizeof(mohandle->mo)); return 0; } @@ -918,17 +997,15 @@ dcngettext(const char *domainname, const domainname, db) == NULL) goto fail; - if (odomainname) - free(odomainname); - if (ocname) - free(ocname); + free(odomainname); + free(ocname); + odomainname = strdup(domainname); ocname = strdup(cname); if (!odomainname || !ocname) { - if (odomainname) - free(odomainname); - if (ocname) - free(ocname); + free(odomainname); + free(ocname); + odomainname = ocname = NULL; } else Index: src/lib/libintl/libintl.h diff -u src/lib/libintl/libintl.h:1.4 src/lib/libintl/libintl.h:1.5 --- src/lib/libintl/libintl.h:1.4 Fri Oct 14 18:42:01 2011 +++ src/lib/libintl/libintl.h Fri May 29 08:26:28 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: libintl.h,v 1.4 2011/10/14 22:42:01 joerg Exp $ */ +/* $NetBSD: libintl.h,v 1.5 2015/05/29 12:26:28 christos Exp $ */ /*- * Copyright (c) 2000 Citrus Project, @@ -31,16 +31,41 @@ #include <sys/cdefs.h> +#define pgettext_expr(msgctxt, msgid) pgettext((msgctxt), (msgid)) +#define dpggettext_expr(domainname, msgctxt, msgid) \ + dpgettext((domainname), (msgctxt), (msgid)) +#define dcpgettext_expr(domainname, msgctxt, msgid, category) \ + dcpgettext((domainname), (msgctxt), (msgid), (category)) +#define npgettext_expr(msgctxt, msgid1, msgid2, n) \ + npgettext((msgctxt), (msgid1), (msgid2), (n)) +#define dnpgettext_expr(domainname, msgctxt, msgid1, n) \ + dnpgettext((domainname), (msgctxt), (msgid1), (msgid2), (n)) +#define dcnpgettext_expr(domainname, msgctxt, msgid1, msgid2, n, category) \ + dcnpgettext((domainname), (msgctxt), (msgid1), (msgid2), (n), (category)) + __BEGIN_DECLS char *gettext(const char *) __format_arg(1); char *dgettext(const char *, const char *) __format_arg(2); char *dcgettext(const char *, const char *, int) __format_arg(2); char *ngettext(const char *, const char *, unsigned long int) - __format_arg(1) __format_arg(2); + __format_arg(1) __format_arg(2); char *dngettext(const char *, const char *, const char *, unsigned long int) - __format_arg(2) __format_arg(3); + __format_arg(2) __format_arg(3); char *dcngettext(const char *, const char *, const char *, unsigned long int, - int) __format_arg(2) __format_arg(3); + int) __format_arg(2) __format_arg(3); +const char *pgettext(const char *, const char *) __format_arg(2); +const char *dpgettext(const char *, const char *, const char *) + __format_arg(3); +const char *dcpgettext(const char *, const char *, const char *, int) + __format_arg(3); +const char *npgettext(const char *, const char *, const char *, + unsigned long int) __format_arg(2) __format_arg(3); +const char *dnpgettext(const char *, const char *, const char *, + const char *, unsigned long int) __format_arg(3) + __format_arg(4); +const char *dcnpgettext(const char *, const char *, const char *, + const char *, unsigned long int, int) __format_arg(3) + __format_arg(4); char *textdomain(const char *); char *bindtextdomain(const char *, const char *); Index: src/lib/libintl/textdomain.c diff -u src/lib/libintl/textdomain.c:1.13 src/lib/libintl/textdomain.c:1.14 --- src/lib/libintl/textdomain.c:1.13 Wed Mar 21 06:10:36 2012 +++ src/lib/libintl/textdomain.c Fri May 29 08:26:28 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: textdomain.c,v 1.13 2012/03/21 10:10:36 matt Exp $ */ +/* $NetBSD: textdomain.c,v 1.14 2015/05/29 12:26:28 christos Exp $ */ /*- * Copyright (c) 2000, 2001 Citrus Project, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: textdomain.c,v 1.13 2012/03/21 10:10:36 matt Exp $"); +__RCSID("$NetBSD: textdomain.c,v 1.14 2015/05/29 12:26:28 christos Exp $"); #include <sys/param.h> @@ -115,8 +115,7 @@ bind_textdomain_codeset(const char *doma return NULL; if (codeset) { - if (p->codeset) - free(p->codeset); + free(p->codeset); p->codeset = strdup(codeset); }