summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2003-02-10 21:07:22 +0000
committerBruno Haible <bruno@clisp.org>2009-06-23 12:08:57 +0200
commit381a0c0f9e065a81ddcba07ffb2baf3e0a3e60b0 (patch)
tree964d67ebcb446255b3c4288f73cae48e2875d4dc
parentbdc66caf57fde3fd4c8feee4926b826851aa0a36 (diff)
downloadexternal_gettext-381a0c0f9e065a81ddcba07ffb2baf3e0a3e60b0.zip
external_gettext-381a0c0f9e065a81ddcba07ffb2baf3e0a3e60b0.tar.gz
external_gettext-381a0c0f9e065a81ddcba07ffb2baf3e0a3e60b0.tar.bz2
New library libgettextpo.
-rw-r--r--ChangeLog4
-rw-r--r--NEWS6
-rw-r--r--PACKAGING2
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/gettext.texi136
-rw-r--r--src/ChangeLog9
-rw-r--r--src/Makefile.am19
-rw-r--r--src/gettext-po.c210
-rw-r--r--src/gettext-po.h95
9 files changed, 483 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 77861cf..f339230 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2003-01-31 Bruno Haible <bruno@clisp.org>
+
+ * PACKAGING: Add gettext-po.h and libgettextpo*.
+
2003-01-03 Albert Chin <libtool@thewrittenword.com>
* ltmain.sh: Don't pass -R flags found in a .la's dependency_libs
diff --git a/NEWS b/NEWS
index d2cacfb..feb0458 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,12 @@ Version 0.11.6 - October 2002
strings in C++. This is needed for proper internationalization of C++
programs.
+* A new include file libgettextpo, with public header file "gettext-po.h",
+ provides functions for reading PO files into memory. It is useful for
+ applying PO files to areas not covered by the GNU gettext programs.
+ New documentation section:
+ - Writing your own programs that process PO files.
+
* xgettext now supports msgid strings in other encodings than ASCII.
xgettext has a new option --from-code that specifies the encoding of the
source files. The resulting POT files are UTF-8 encoded.
diff --git a/PACKAGING b/PACKAGING
index fafad36..2677fbb 100644
--- a/PACKAGING
+++ b/PACKAGING
@@ -64,8 +64,10 @@ following file list.
$prefix/doc/libasprintf/autosprintf.html
$prefix/info/gettext.info*
$prefix/info/autosprintf.info
+ $prefix/include/gettext-po.h
$prefix/lib/libgettextlib*
$prefix/lib/libgettextsrc*
+ $prefix/lib/libgettextpo*
$prefix/lib/gettext/*
$prefix/share/locale/*/LC_MESSAGES/gettext.mo
$prefix/share/gettext/config.rpath
diff --git a/doc/ChangeLog b/doc/ChangeLog
index b5447e1..38ed3b0 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2003-01-31 Bruno Haible <bruno@clisp.org>
+
+ * gettext.texi (libgettextpo): New node.
+
2003-01-24 Bruno Haible <bruno@clisp.org>
* msgattrib.texi: Document options --only-file and --ignore-file.
diff --git a/doc/gettext.texi b/doc/gettext.texi
index 6bad1e3..cd9bd6a 100644
--- a/doc/gettext.texi
+++ b/doc/gettext.texi
@@ -212,6 +212,7 @@ Manipulating PO Files
* msgattrib Invocation:: Invoking the @code{msgattrib} Program
* msgen Invocation:: Invoking the @code{msgen} Program
* msgexec Invocation:: Invoking the @code{msgexec} Program
+* libgettextpo:: Writing your own programs that process PO files
Producing Binary MO Files
@@ -3637,6 +3638,10 @@ or untranslated messages of a translation catalog.
@samp{msgen} is useful as a first step for preparing English translation
catalogs. It copies each message's msgid to its msgstr.
+Finally, for those applications where all these various programs are not
+sufficient, a library @samp{libgettextpo} is provided that can be used to
+write other specialized programs that process PO files.
+
@menu
* msgcat Invocation:: Invoking the @code{msgcat} Program
* msgconv Invocation:: Invoking the @code{msgconv} Program
@@ -3648,6 +3653,7 @@ catalogs. It copies each message's msgid to its msgstr.
* msgattrib Invocation:: Invoking the @code{msgattrib} Program
* msgen Invocation:: Invoking the @code{msgen} Program
* msgexec Invocation:: Invoking the @code{msgexec} Program
+* libgettextpo:: Writing your own programs that process PO files
@end menu
@node msgcat Invocation, msgconv Invocation, Manipulating, Manipulating
@@ -3695,11 +3701,139 @@ catalogs. It copies each message's msgid to its msgstr.
@include msgen.texi
-@node msgexec Invocation, , msgen Invocation, Manipulating
+@node msgexec Invocation, libgettextpo, msgen Invocation, Manipulating
@section Invoking the @code{msgexec} Program
@include msgexec.texi
+@node libgettextpo, , msgexec Invocation, Manipulating
+@section Writing your own programs that process PO files
+
+For the tasks for which a combination of @samp{msgattrib}, @samp{msgcat} etc.
+is not sufficient, a set of C functions is provided in a library, to make it
+possible to process PO files in your own programs. When you use this library,
+you don't need to write routines to parse the PO file; instead, you retreive
+a pointer in memory to each of messages contained in the PO file. Functions
+for writing PO files are not provided at this time.
+
+The functions are declared in the header file @samp{<gettext-po.h>}, and are
+defined in a library called @samp{libgettextpo}.
+
+@deftp {Data Type} po_file_t
+This is a pointer type that refers to the contents of a PO file, after it has
+been read into memory.
+@end deftp
+
+@deftp {Data Type} po_message_iterator_t
+This is a pointer type that refers to an iterator that produces a sequence of
+messages.
+@end deftp
+
+@deftp {Data Type} po_message_t
+This is a pointer type that refers to a message of a PO file, including its
+translation.
+@end deftp
+
+@deftypefun po_file_t po_file_read (const char *@var{filename})
+The @code{po_file_read} function reads a PO file into memory. The file name
+is given as argument. The return value is a handle to the PO file's contents,
+valid until @code{po_file_free} is called on it. In case of error, the return
+value is @code{NULL}, and @code{errno} is set.
+@end deftypefun
+
+@deftypefun void po_file_free (po_file_t @var{file})
+The @code{po_file_free} function frees a PO file's contents from memory,
+including all messages that are only implicitly accessible through iterators.
+@end deftypefun
+
+@deftypefun {const char * const *} po_file_domains (po_file_t @var{file})
+The @code{po_file_domains} function returns the domains for which the given
+PO file has messages. The return value is a @code{NULL} terminated array
+which is valid as long as the @var{file} handle is valid. For PO files which
+contain no @samp{domain} directive, the return value contains only one domain,
+namely the default domain @code{"messages"}.
+@end deftypefun
+
+@deftypefun po_message_iterator_t po_message_iterator (po_file_t @var{file}, const char *@var{domain})
+The @code{po_message_iterator} returns an iterator that will produce the
+messages of @var{file} that belong to the given @var{domain}. If @var{domain}
+is @code{NULL}, the default domain is used instead. To list the messages,
+use the function @code{po_next_message} repeatedly.
+@end deftypefun
+
+@deftypefun void po_message_iterator_free (po_message_iterator_t @var{iterator})
+The @code{po_message_iterator_free} function frees an iterator previously
+allocated through the @code{po_message_iterator} function.
+@end deftypefun
+
+@deftypefun po_message_t po_next_message (po_message_iterator_t @var{iterator})
+The @code{po_next_message} function returns the next message from
+@var{iterator} and advances the iterator. It returns @code{NULL} when the
+iterator has reached the end of its message list.
+@end deftypefun
+
+The following functions returns details of a @code{po_message_t}. Recall
+that the results are valid as long as the @var{file} handle is valid.
+
+@deftypefun {const char *} po_message_msgid (po_message_t @var{message})
+The @code{po_message_msgid} function returns the @code{msgid} (untranslated
+English string) of a message. This is guaranteed to be non-@code{NULL}.
+@end deftypefun
+
+@deftypefun {const char *} po_message_msgid_plural (po_message_t @var{message})
+The @code{po_message_msgid_plural} function returns the @code{msgid_plural}
+(untranslated English plural string) of a message with plurals, or @code{NULL}
+for a message without plural.
+@end deftypefun
+
+@deftypefun {const char *} po_message_msgstr (po_message_t @var{message})
+The @code{po_message_msgstr} function returns the @code{msgstr} (translation)
+of a message. For an untranslated message, the return value is an empty
+string.
+@end deftypefun
+
+@deftypefun {const char *} po_message_msgstr_plural (po_message_t @var{message}, int @var{index})
+The @code{po_message_msgstr_plural} function returns the
+@code{msgstr[@var{index}]} of a message with plurals, or @code{NULL} when
+the @var{index} is out of range or for a message without plural.
+@end deftypefun
+
+Here is an example code how these functions can be used.
+
+@example
+const char *filename = @dots{};
+po_file_t file = po_file_read (filename);
+
+if (file == NULL)
+ error (EXIT_FAILURE, errno, "couldn't open the PO file %s", filename);
+@{
+ const char * const *domains = po_file_domains (file);
+ const char * const *domainp;
+
+ for (domainp = domains; *domainp; domainp++)
+ @{
+ const char *domain = *domainp;
+ po_message_iterator_t iterator = po_message_iterator (file, domain);
+
+ for (;;)
+ @{
+ po_message_t *message = po_next_message (iterator);
+
+ if (message == NULL)
+ break;
+ @{
+ const char *msgid = po_message_msgid (message);
+ const char *msgstr = po_message_msgstr (message);
+
+ @dots{}
+ @}
+ @}
+ po_message_iterator_free (iterator);
+ @}
+@}
+po_file_free (file);
+@end example
+
@node Binaries, Users, Manipulating, Top
@chapter Producing Binary MO Files
diff --git a/src/ChangeLog b/src/ChangeLog
index 71c8c27..1f86671 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
+2003-01-31 Bruno Haible <bruno@clisp.org>
+
+ * gettext-po.h: New file.
+ * gettext-po.c: New file.
+ * Makefile.am (lib_LTLIBRARIES): Add libgettextpo.la.
+ (include_HEADERS): New variable.
+ (libgettextpo_la_SOURCES, libgettextpo_la_LDFLAGS): New variables.
+ (LTV_CURRENT, LTV_REVISION, LTV_AGE): New variables.
+
2003-01-24 Bruno Haible <bruno@clisp.org>
* msgattrib.c (long_options): Add --only-file and --ignore-file.
diff --git a/src/Makefile.am b/src/Makefile.am
index f5910de..9652fa0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,9 @@ msgattrib msgcat msgcomm msgconv msgen msgexec msgfilter msggrep msginit msguniq
noinst_PROGRAMS = hostname urlget
-lib_LTLIBRARIES = libgettextsrc.la
+lib_LTLIBRARIES = libgettextsrc.la libgettextpo.la
+
+include_HEADERS = gettext-po.h
noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \
po.h open-po.h read-po.h str-list.h write-po.h dir-list.h file-list.h \
@@ -86,6 +88,14 @@ $(COMMON_SOURCE) read-po.c write-po.c msgl-ascii.c msgl-iconv.c msgl-equal.c \
msgl-cat.c msgl-english.c file-list.c msgl-charset.c po-time.c plural.c \
plural-table.c $(FORMAT_SOURCE)
+# libgettextpo contains the public API for PO files.
+libgettextpo_la_SOURCES = gettext-po.c
+# Libtool's library version information for libgettextpo.
+# See the libtool documentation, section "Library interface versions".
+LTV_CURRENT=0
+LTV_REVISION=0
+LTV_AGE=0
+
# x-python needs table of Unicode character names.
LIBUNINAME = ../libuniname/libuniname.a
@@ -126,6 +136,13 @@ install-exec-am: install-exec-clean
install-exec-clean:
$(RM) $(DESTDIR)$(libdir)/libgettextsrc.a
+# How to build libgettextpo.la.
+# Need libgettextsrc.la.
+libgettextpo_la_LDFLAGS = \
+ -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
+ -rpath $(libdir) \
+ libgettextsrc.la -lc -no-undefined
+
# Link dependencies.
gettext_LDADD = ../lib/basename.lo ../lib/error.lo ../lib/getopt.lo ../lib/getopt1.lo ../lib/strtoul.lo ../lib/xmalloc.lo @LTLIBINTL@
ngettext_LDADD = ../lib/basename.lo ../lib/error.lo ../lib/getopt.lo ../lib/getopt1.lo ../lib/strtoul.lo ../lib/xmalloc.lo @LTLIBINTL@
diff --git a/src/gettext-po.c b/src/gettext-po.c
new file mode 100644
index 0000000..85dc4ac
--- /dev/null
+++ b/src/gettext-po.c
@@ -0,0 +1,210 @@
+/* Public API for GNU gettext PO files.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "gettext-po.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "message.h"
+#include "xmalloc.h"
+#include "read-po.h"
+
+
+struct po_file
+{
+ msgdomain_list_ty *mdlp;
+ const char *real_filename;
+ const char *logical_filename;
+ const char **domains;
+};
+
+struct po_message_iterator
+{
+ message_list_ty *mlp;
+ size_t index;
+};
+
+/* A po_message_t is actually a 'struct message_ty *'. */
+
+
+/* Read a PO file into memory.
+ Return its contents. Upon failure, return NULL and set errno. */
+
+po_file_t
+po_file_read (const char *filename)
+{
+ FILE *fp;
+ po_file_t file;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ return NULL;
+ file = (struct po_file *) xmalloc (sizeof (struct po_file));
+ file->real_filename = filename;
+ file->logical_filename = filename;
+ file->mdlp = read_po (fp, file->real_filename, file->logical_filename);
+ file->domains = NULL;
+ fclose (fp);
+ return file;
+}
+
+
+/* Free a PO file from memory. */
+
+void
+po_file_free (po_file_t file)
+{
+ msgdomain_list_free (file->mdlp);
+ if (file->domains != NULL)
+ free (file->domains);
+ free (file);
+}
+
+
+/* Return the names of the domains covered by a PO file in memory. */
+
+const char * const *
+po_file_domains (po_file_t file)
+{
+ if (file->domains == NULL)
+ {
+ size_t n = file->mdlp->nitems;
+ const char **domains =
+ (const char **) xmalloc ((n + 1) * sizeof (const char *));
+ size_t j;
+
+ for (j = 0; j < n; j++)
+ domains[j] = file->mdlp->item[j]->domain;
+ domains[n] = NULL;
+
+ file->domains = domains;
+ }
+
+ return file->domains;
+}
+
+
+/* Create an iterator for traversing a domain of a PO file in memory.
+ The domain NULL denotes the default domain. */
+
+po_message_iterator_t
+po_message_iterator (po_file_t file, const char *domain)
+{
+ po_message_iterator_t iterator;
+
+ if (domain == NULL)
+ domain = MESSAGE_DOMAIN_DEFAULT;
+
+ iterator =
+ (struct po_message_iterator *)
+ xmalloc (sizeof (struct po_message_iterator));
+ iterator->mlp = msgdomain_list_sublist (file->mdlp, domain, false);
+ iterator->index = 0;
+
+ return iterator;
+}
+
+
+/* Free an iterator. */
+
+void
+po_message_iterator_free (po_message_iterator_t iterator)
+{
+ free (iterator);
+}
+
+
+/* Return the next message, and advance the iterator.
+ Return NULL at the end of the message list. */
+
+po_message_t
+po_next_message (po_message_iterator_t iterator)
+{
+ if (iterator->index < iterator->mlp->nitems)
+ return (po_message_t) iterator->mlp->item[iterator->index++];
+ else
+ return NULL;
+}
+
+
+/* Return the msgid (untranslated English string) of a message. */
+
+const char *
+po_message_msgid (po_message_t message)
+{
+ message_ty *mp = (message_ty *) message;
+
+ return mp->msgid;
+}
+
+
+/* Return the msgid_plural (untranslated English plural string) of a message,
+ or NULL for a message without plural. */
+
+const char *
+po_message_msgid_plural (po_message_t message)
+{
+ message_ty *mp = (message_ty *) message;
+
+ return mp->msgid_plural;
+}
+
+
+/* Return the msgstr (translation) of a message.
+ Return the empty string for an untranslated message. */
+
+const char *
+po_message_msgstr (po_message_t message)
+{
+ message_ty *mp = (message_ty *) message;
+
+ return mp->msgstr;
+}
+
+
+/* Return the msgstr[index] for a message with plural handling, or
+ NULL when the index is out of range or for a message without plural. */
+
+const char *
+po_message_msgstr_plural (po_message_t message, int index)
+{
+ message_ty *mp = (message_ty *) message;
+
+ if (mp->msgid_plural != NULL && index >= 0)
+ {
+ const char *p;
+ const char *p_end = mp->msgstr + mp->msgstr_len;
+
+ for (p = mp->msgstr; ; p += strlen (p) + 1, index--)
+ {
+ if (p >= p_end)
+ return NULL;
+ if (index == 0)
+ break;
+ }
+ return p;
+ }
+ else
+ return NULL;
+}
diff --git a/src/gettext-po.h b/src/gettext-po.h
new file mode 100644
index 0000000..27788e6
--- /dev/null
+++ b/src/gettext-po.h
@@ -0,0 +1,95 @@
+/* Public API for GNU gettext PO files - contained in libgettextpo.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETTEXT_PO_H
+#define _GETTEXT_PO_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ================================= Types ================================= */
+
+/* A po_file_t represents the contents of a PO file. */
+typedef struct po_file *po_file_t;
+
+/* A po_message_iterator_t represents an iterator through a domain of a
+ PO file. */
+typedef struct po_message_iterator *po_message_iterator_t;
+
+/* A po_message_t represents a message in a PO file. */
+typedef struct po_message *po_message_t;
+
+/* Memory allocation:
+ The memory allocations performed by these functions use xmalloc(),
+ therefore will cause a program exit if memory is exhausted.
+ The memory allocated by po_file_read, and implicitly returned through
+ the po_message_* functions, lasts until freed with po_file_free. */
+
+
+/* ============================= po_file_t API ============================= */
+
+/* Read a PO file into memory.
+ Return its contents. Upon failure, return NULL and set errno. */
+extern po_file_t po_file_read (const char *filename);
+
+/* Free a PO file from memory. */
+extern void po_file_free (po_file_t file);
+
+/* Return the names of the domains covered by a PO file in memory. */
+extern const char * const * po_file_domains (po_file_t file);
+
+
+/* ======================= po_message_iterator_t API ======================= */
+
+/* Create an iterator for traversing a domain of a PO file in memory.
+ The domain NULL denotes the default domain. */
+extern po_message_iterator_t po_message_iterator (po_file_t file, const char *domain);
+
+/* Free an iterator. */
+extern void po_message_iterator_free (po_message_iterator_t iterator);
+
+/* Return the next message, and advance the iterator.
+ Return NULL at the end of the message list. */
+extern po_message_t po_next_message (po_message_iterator_t iterator);
+
+
+/* =========================== po_message_t API ============================ */
+
+/* Return the msgid (untranslated English string) of a message. */
+extern const char * po_message_msgid (po_message_t message);
+
+/* Return the msgid_plural (untranslated English plural string) of a message,
+ or NULL for a message without plural. */
+extern const char * po_message_msgid_plural (po_message_t message);
+
+/* Return the msgstr (translation) of a message.
+ Return the empty string for an untranslated message. */
+extern const char * po_message_msgstr (po_message_t message);
+
+/* Return the msgstr[index] for a message with plural handling, or
+ NULL when the index is out of range or for a message without plural. */
+extern const char * po_message_msgstr_plural (po_message_t message, int index);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETTEXT_PO_H */