]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
New library libgettextpo.
authorBruno Haible <bruno@clisp.org>
Mon, 10 Feb 2003 21:07:22 +0000 (21:07 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:08:57 +0000 (12:08 +0200)
ChangeLog
NEWS
PACKAGING
doc/ChangeLog
doc/gettext.texi
src/ChangeLog
src/Makefile.am
src/gettext-po.c [new file with mode: 0644]
src/gettext-po.h [new file with mode: 0644]

index 77861cf294c3256e81d22b6c96fc506be7ea52c7..f339230fa623d8578d5f1890d237821118a03621 100644 (file)
--- 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 d2cacfbee46fdfbcbb8f42b8a47030196bda33b3..feb0458e48b7ad76c7efe28c134aefd491e8c8d9 100644 (file)
--- 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.
index fafad36a944447e5f074a7443441ffb7708423e8..2677fbbf5d40dd92d7c031289dc129a5af4a4e17 100644 (file)
--- 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
index b5447e107ec66e1500c905561d67d049f2bbafe1..38ed3b0366f81b524ca82230b4c801ff608fe15d 100644 (file)
@@ -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.
index 6bad1e334f5e4d60f0bc0d53f45383b51a5b92f8..cd9bd6a01206c26b2dc24b9170cd522bf1c685e9 100644 (file)
@@ -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
 
index 71c8c279f4309ca80fd5c377ab7306f340b8d857..1f866719031f9ff4dd53fbb85ced3119ea52fb4f 100644 (file)
@@ -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.
index f5910deba96ffa8ba80bbed7acfd480c88143aa4..9652fa0a4c0ecf5f0d9e3890a760d412755e8f5a 100644 (file)
@@ -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 (file)
index 0000000..85dc4ac
--- /dev/null
@@ -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 (file)
index 0000000..27788e6
--- /dev/null
@@ -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 */