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);
 	}
 

Reply via email to