]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Extend the gettexpo library.
authorBruno Haible <bruno@clisp.org>
Tue, 7 Sep 2004 11:44:32 +0000 (11:44 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:54 +0000 (12:11 +0200)
Use custom error handlers during reading and writing of PO files.

21 files changed:
gettext-tools/ChangeLog
gettext-tools/po/ChangeLog
gettext-tools/po/Makevars
gettext-tools/src/ChangeLog
gettext-tools/src/FILES
gettext-tools/src/Makefile.am
gettext-tools/src/Makefile.msvc
gettext-tools/src/Makefile.vms
gettext-tools/src/gettext-po.c
gettext-tools/src/gettext-po.h
gettext-tools/src/message.c
gettext-tools/src/message.h
gettext-tools/src/po-charset.c
gettext-tools/src/po-lex.c
gettext-tools/src/po-lex.h
gettext-tools/src/read-po-abstract.c
gettext-tools/src/str-list.c
gettext-tools/src/str-list.h
gettext-tools/src/write-po.c
gettext-tools/windows/gettextpo.def
gettext-tools/windows/gettextsrc.def

index c46ed6c9568fc3e7e2c9186d9efed7455786e426..ef3a0f8fe996f52ef51a762b2633bb8e34ef7775 100644 (file)
@@ -1,3 +1,8 @@
+2004-09-05  Bruno Haible  <bruno@clisp.org>
+
+       * windows/gettextsrc.def: Add the variables names from po-error.h.
+       * windows/gettextpo.def: Add many new function names.
+
 2004-04-19  Bruno Haible  <bruno@clisp.org>
 
        * gettext.m4: Change jm_ to gl_ in all uses of AC_DEFINE'd names.
index 56cac390ddd75e8606084425cb3d44a4b7fd016d..7a829ddb8f18d98f0dafdbb7eb0e67809017c6d1 100644 (file)
@@ -1,3 +1,7 @@
+2004-09-05  Bruno Haible  <bruno@clisp.org>
+
+       * Makevars (XGETTEXT_OPTIONS): Recognize po_error and po_error_at_line.
+
 2004-03-21  Bruno Haible  <bruno@clisp.org>
 
        * ca.po: Update from Ivan Vilata i Balaguer <ivan@selidor.net>.
index 17be10a4e9f43f18698e7b6d141541182630d8da..e1f13d6c7b2f3f981cbbdc29b9fbc96233a7f854 100644 (file)
@@ -14,6 +14,7 @@ XGETTEXT_OPTIONS = \
   --flag=error:3:c-format --flag=error_at_line:5:c-format \
   --flag=asprintf:2:c-format --flag=vasprintf:2:c-format \
   --flag=xasprintf:1:c-format \
+  --flag=po_error:3:c-format --flag=po_error_at_line:5:c-format \
   --flag=po_gram_error:1:c-format --flag=po_gram_error_at_line:2:c-format
 
 # This is the copyright holder that gets inserted into the header of the
index 1cc6a72ca547a2e10fdb1b7ef0870f62abc40f56..781c550fdbd5b1878546c6fbc7297f22b2575328 100644 (file)
@@ -1,3 +1,62 @@
+2004-09-05  Bruno Haible  <bruno@clisp.org>
+
+       * po-error.h: New file.
+       * po-error.c: New file.
+       * po-charset.c: Include po-error.h.
+       (po_lex_charset_set): Use po_multiline_warning instead of
+       multiline_warning.
+       * po-lex.h: Include po-error.h.
+       (po_gram_error): Use po_error instead of error.
+       (po_gram_error_at_line): Use po_error_at_line instead of error_at_line.
+       * po-lex.c (po_gram_error): Use po_error instead of error.
+       (po_gram_error_at_line): Use po_error_at_line instead of error_at_line.
+       (mbfile_getc, lex_getc): Use po_error instead of error.
+       * read-po-abstract.c (po_scan): Likewise.
+       * write-po.c: Include po-error.h instead of error.h.
+       (wrap): Use po_error instead of error.
+       (message_print, message_print_obsolete): Use po_multiline_warning
+       instead of multiline_warning.
+       (msgdomain_list_print): Use po_error instead of error, po_error_at_line
+       instead of error_at_line.
+       * str-list.h (string_list_join): New declaration.
+       * str-list.c (string_list_join): New function.
+       * message.h (message_list_insert_at): New declaration.
+       * message.c (message_list_insert_at): New function.
+       * gettext-po.h (po_filepos_t): New type.
+       (struct po_error_handler, po_error_handler_t): New types.
+       (po_file_create): New declaration.
+       (po_file_read): Add handler argument.
+       (po_file_write, po_message_insert, po_message_create,
+       po_message_set_msgid, po_message_set_msgid_plural,
+       po_message_set_msgstr, po_message_set_msgstr_plural,
+       po_message_comments, po_message_set_comments,
+       po_message_extracted_comments, po_message_filepos,
+       po_message_set_obsolete, po_message_set_fuzzy, po_message_set_format,
+       po_filepos_file, po_filepos_start_line): New declarations.
+       * gettext-po.c (po_file_create): New function.
+       (po_file_read): Add handler argument. Keep an old version for backward
+       compatibility.
+       (po_file_write): New function.
+       (po_message_iterator): Store more information, to make
+       po_message_insert possible.
+       (po_message_iterator_free): Update.
+       (po_next_message): Don't crash if iterator->mlp is NULL.
+       (po_message_insert): New function.
+       (po_message_create): New function.
+       (po_message_set_msgid, po_message_set_msgid_plural,
+       po_message_set_msgstr, po_message_set_msgstr_plural,
+       po_message_comments, po_message_set_comments,
+       po_message_extracted_comments, po_message_filepos,
+       po_message_set_obsolete, po_message_set_fuzzy, po_message_set_format,
+       po_filepos_file, po_filepos_start_line): New functions.
+       * Makefile.am (noinst_HEADERS): Add po-error.h.
+       (COMMON_SOURCE): Add po-error.c.
+       * Makefile.msvc (OBJECTS): Add po-error.obj.
+       (po-error.obj): New rule.
+       * Makefile.vms (OBJECTS): Add po-error.obj.
+       (po-error.obj): New rule.
+       * FILES: Update.
+
 2004-09-03  Bruno Haible  <bruno@clisp.org>
 
        * Makefile.am (msginit_LDADD): Use the INTL_MACOSX_LDFLAGS.
index 40fed3772569c6e59dcd42e570c82ae5bd46bf5f..d5f76e8d7a27aa760785f958085b7fcb2d9a4121 100644 (file)
@@ -32,6 +32,10 @@ msgl-ascii.h
 msgl-ascii.c
                 Message list test for ASCII character set.
 
+po-error.h
+po-error.c
+                Error handling during writing and reading of PO files.
+
 write-po.h
 write-po.c
                 Output of a list-of-messages to a PO file.
index 266d072f0a0e4d7d7c36123600857b8ab37e05c6..36f129ac87e2992b8a5a7d38b6b757bc0da02c57 100644 (file)
@@ -34,14 +34,21 @@ 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 \
-open-po.h read-po-abstract.h read-po.h read-properties.h read-stringtable.h \
-str-list.h write-po.h write-properties.h write-stringtable.h dir-list.h \
-file-list.h po-gram-gen.h po-gram-gen2.h po-hash-gen.h msgl-charset.h \
-msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-english.h msgfmt.h \
-msgunfmt.h plural-count.h read-mo.h write-mo.h read-java.h write-java.h \
-read-csharp.h write-csharp.h read-resources.h write-resources.h read-tcl.h \
-write-tcl.h write-qt.h po-time.h plural-table.h format.h \
+noinst_HEADERS = pos.h message.h po-error.h po-gram.h po-hash.h po-charset.h \
+po-lex.h open-po.h \
+read-po-abstract.h read-po.h read-properties.h read-stringtable.h \
+str-list.h \
+write-po.h write-properties.h write-stringtable.h \
+dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h po-hash-gen.h \
+msgl-charset.h msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h \
+msgl-english.h msgfmt.h msgunfmt.h plural-count.h \
+read-mo.h write-mo.h \
+read-java.h write-java.h \
+read-csharp.h write-csharp.h \
+read-resources.h write-resources.h \
+read-tcl.h write-tcl.h \
+write-qt.h \
+po-time.h plural-table.h format.h \
 xgettext.h x-c.h x-po.h x-sh.h x-python.h x-lisp.h x-elisp.h x-librep.h \
 x-smalltalk.h x-java.h x-properties.h x-csharp.h x-awk.h x-ycp.h x-tcl.h \
 x-perl.h x-php.h x-stringtable.h x-rst.h x-glade.h
@@ -90,7 +97,7 @@ CSHARPCOMPFLAGS = -O -g
 # (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> open-po.c -> dir-list.c -> str-list.c.
 # (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> po-charset.c.
 # (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> message.c -> str-list.c.
-COMMON_SOURCE = message.c \
+COMMON_SOURCE = message.c po-error.c \
 read-po-abstract.c po-lex.c po-gram-gen.y po-hash-gen.y po-charset.c \
 read-properties.c read-stringtable.c open-po.c dir-list.c str-list.c
 
index 00079b432a134a3f9501b91c0e5a27d464c5816e..27bdbf2c9f1332ceb32f88875381f85bc748417f 100644 (file)
@@ -106,6 +106,7 @@ msgattrib.exe msgcat.exe msgcomm.exe msgconv.exe msgen.exe msgexec.exe msgfilter
 
 OBJECTS = \
   message.obj \
+  po-error.obj \
   read-po-abstract.obj \
   po-lex.obj \
   po-gram-gen.obj \
@@ -175,6 +176,9 @@ all : gettextsrc.lib $(PROGRAMS) gettextpo.lib
 message.obj : message.c
        $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c message.c
 
+po-error.obj : po-error.c
+       $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c -Tp po-error.c
+
 read-po-abstract.obj : read-po-abstract.c
        $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c read-po-abstract.c
 
index 7445330deda56e2372e76fe3b7e3069e0285eefc..53fb4e495ebc0054bdfc70feeff5934cbadee76f 100644 (file)
@@ -52,6 +52,7 @@ PROGRAMS = msgcmp.exe, msgfmt.exe, msgmerge.exe, msgunfmt.exe, xgettext.exe, msg
 
 OBJECTS = \
   message.obj, \
+  po-error.obj, \
   read-po-abstract.obj, \
   po-lex.obj, \
   po-gram-gen.obj, \
@@ -119,6 +120,9 @@ all : gettextsrc.olb,$(PROGRAMS),gettextpo.olb
 message.obj : message.c
        $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) message.c
 
+po-error.obj : po-error.c
+       $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) po-error.c
+
 read-po-abstract.obj : read-po-abstract.c
        $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) read-po-abstract.c
 
index 611a2fbd87d19e63b887bcdb5757c968295f74df..2a4e6252229c9c72a7a8d5e869304cd4f065dfe3 100644 (file)
@@ -1,5 +1,5 @@
 /* Public API for GNU gettext PO files.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.
 
    This program is free software; you can redistribute it and/or modify
 /* Specification.  */
 #include "gettext-po.h"
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "message.h"
 #include "xalloc.h"
 #include "read-po.h"
+#include "write-po.h"
+#include "error.h"
+#include "xerror.h"
+#include "po-error.h"
+#include "gettext.h"
+
+#define _(str) gettext(str)
 
 
 struct po_file
@@ -41,16 +49,70 @@ struct po_file
 
 struct po_message_iterator
 {
+  po_file_t file;
+  char *domain;
   message_list_ty *mlp;
   size_t index;
 };
 
 /* A po_message_t is actually a 'struct message_ty *'.  */
 
+/* A po_filepos_t is actually a 'lex_pos_ty *'.  */
+
+
+/* Create an empty PO file representation in memory.  */
+
+po_file_t
+po_file_create (void)
+{
+  po_file_t file;
+
+  file = (struct po_file *) xmalloc (sizeof (struct po_file));
+  file->mdlp = msgdomain_list_alloc (false);
+  file->real_filename = _("<unnamed>");
+  file->logical_filename = file->real_filename;
+  file->domains = NULL;
+  return file;
+}
+
 
 /* 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, po_error_handler_t handler)
+{
+  FILE *fp;
+  po_file_t file;
+
+  fp = fopen (filename, "r");
+  if (fp == NULL)
+    return NULL;
+
+  /* Establish error handler around read_po().  */
+  po_error             = handler->error;
+  po_error_at_line     = handler->error_at_line;
+  po_multiline_warning = handler->multiline_warning;
+  po_multiline_error   = handler->multiline_error;
+
+  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;
+
+  /* Restore error handler.  */
+  po_error             = error;
+  po_error_at_line     = error_at_line;
+  po_multiline_warning = multiline_warning;
+  po_multiline_error   = multiline_error;
+
+  fclose (fp);
+  return file;
+}
+#undef po_file_read
+
+/* Older version for binary backward compatibility.  */
 po_file_t
 po_file_read (const char *filename)
 {
@@ -60,16 +122,42 @@ po_file_read (const char *filename)
   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;
 }
 
 
+/* Write an in-memory PO file to a file.
+   Upon failure, return NULL and set errno.  */
+
+po_file_t
+po_file_write (po_file_t file, const char *filename, po_error_handler_t handler)
+{
+  /* Establish error handler around msgdomain_list_print().  */
+  po_error             = handler->error;
+  po_error_at_line     = handler->error_at_line;
+  po_multiline_warning = handler->multiline_warning;
+  po_multiline_error   = handler->multiline_error;
+
+  msgdomain_list_print (file->mdlp, filename, true, false);
+
+  /* Restore error handler.  */
+  po_error             = error;
+  po_error_at_line     = error_at_line;
+  po_multiline_warning = multiline_warning;
+  po_multiline_error   = multiline_error;
+
+  return file;
+}
+
+
 /* Free a PO file from memory.  */
 
 void
@@ -189,6 +277,8 @@ po_message_iterator (po_file_t file, const char *domain)
   iterator =
     (struct po_message_iterator *)
     xmalloc (sizeof (struct po_message_iterator));
+  iterator->file = file;
+  iterator->domain = xstrdup (domain);
   iterator->mlp = msgdomain_list_sublist (file->mdlp, domain, false);
   iterator->index = 0;
 
@@ -201,6 +291,7 @@ po_message_iterator (po_file_t file, const char *domain)
 void
 po_message_iterator_free (po_message_iterator_t iterator)
 {
+  free (iterator->domain);
   free (iterator);
 }
 
@@ -211,13 +302,45 @@ po_message_iterator_free (po_message_iterator_t iterator)
 po_message_t
 po_next_message (po_message_iterator_t iterator)
 {
-  if (iterator->index < iterator->mlp->nitems)
+  if (iterator->mlp != NULL && iterator->index < iterator->mlp->nitems)
     return (po_message_t) iterator->mlp->item[iterator->index++];
   else
     return NULL;
 }
 
 
+/* Insert a message in a PO file in memory, in the domain and at the position
+   indicated by the iterator.  The iterator thereby advances past the freshly
+   inserted message.  */
+
+void
+po_message_insert (po_message_iterator_t iterator, po_message_t message)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (iterator->mlp == NULL)
+    /* Now we need to allocate a sublist corresponding to the iterator.  */
+    iterator->mlp =
+      msgdomain_list_sublist (iterator->file->mdlp, iterator->domain, true);
+  /* Insert the message.  */
+  message_list_insert_at (iterator->mlp, iterator->index, mp);
+  /* Advance the iterator.  */
+  iterator->index++;
+}
+
+
+/* Return a freshly constructed message.
+   To finish initializing the message, you must set the msgid and msgstr.  */
+
+po_message_t
+po_message_create (void)
+{
+  lex_pos_ty pos = { NULL, 0 };
+
+  return (po_message_t) message_alloc (NULL, NULL, NULL, 0, &pos);
+}
+
+
 /* Return the msgid (untranslated English string) of a message.  */
 
 const char *
@@ -229,6 +352,24 @@ po_message_msgid (po_message_t message)
 }
 
 
+/* Change the msgid (untranslated English string) of a message.  */
+
+void
+po_message_set_msgid (po_message_t message, const char *msgid)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (msgid != mp->msgid)
+    {
+      char *old_msgid = (char *) mp->msgid;
+
+      mp->msgid = xstrdup (msgid);
+      if (old_msgid != NULL)
+       free (old_msgid);
+    }
+}
+
+
 /* Return the msgid_plural (untranslated English plural string) of a message,
    or NULL for a message without plural.  */
 
@@ -241,6 +382,25 @@ po_message_msgid_plural (po_message_t message)
 }
 
 
+/* Change the msgid_plural (untranslated English plural string) of a message.
+   NULL means a message without plural.  */
+
+void
+po_message_set_msgid_plural (po_message_t message, const char *msgid_plural)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (msgid_plural != mp->msgid_plural)
+    {
+      char *old_msgid_plural = (char *) mp->msgid_plural;
+
+      mp->msgid_plural = (msgid_plural != NULL ? xstrdup (msgid_plural) : NULL);
+      if (old_msgid_plural != NULL)
+       free (old_msgid_plural);
+    }
+}
+
+
 /* Return the msgstr (translation) of a message.
    Return the empty string for an untranslated message.  */
 
@@ -253,6 +413,26 @@ po_message_msgstr (po_message_t message)
 }
 
 
+/* Change the msgstr (translation) of a message.
+   Use an empty string to denote an untranslated message.  */
+
+void
+po_message_set_msgstr (po_message_t message, const char *msgstr)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (msgstr != mp->msgstr)
+    {
+      char *old_msgstr = (char *) mp->msgstr;
+
+      mp->msgstr = xstrdup (msgstr);
+      mp->msgstr_len = strlen (mp->msgstr) + 1;
+      if (old_msgstr != NULL)
+       free (old_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.  */
 
@@ -280,6 +460,170 @@ po_message_msgstr_plural (po_message_t message, int index)
 }
 
 
+/* Change the msgstr[index] for a message with plural handling.
+   Use a NULL value at the end to reduce the number of plural forms.  */
+
+void
+po_message_set_msgstr_plural (po_message_t message, int index, const char *msgstr)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (mp->msgid_plural != NULL && index >= 0)
+    {
+      char *p = (char *) mp->msgstr;
+      char *p_end = (char *) mp->msgstr + mp->msgstr_len;
+      char *copied_msgstr;
+
+      /* Special care must be taken of the case that msgstr points into the
+        mp->msgstr string list, because mp->msgstr may be relocated before we
+        are done with msgstr.  */
+      if (msgstr >= p && msgstr < p_end)
+       msgstr = copied_msgstr = xstrdup (msgstr);
+      else
+       copied_msgstr = NULL;
+
+      for (; ; p += strlen (p) + 1, index--)
+       {
+         if (p >= p_end)
+           {
+             /* Append at the end.  */
+             if (msgstr != NULL)
+               {
+                 size_t new_msgstr_len = mp->msgstr_len + index + strlen (msgstr) + 1;
+
+                 mp->msgstr =
+                   (char *) xrealloc ((char *) mp->msgstr, new_msgstr_len);
+                 p = (char *) mp->msgstr + mp->msgstr_len;
+                 for (; index > 0; index--)
+                   *p++ = '\0';
+                 memcpy (p, msgstr, strlen (msgstr) + 1);
+                 mp->msgstr_len = new_msgstr_len;
+               }
+             if (copied_msgstr != NULL)
+               free (copied_msgstr);
+             return;
+           }
+         if (index == 0)
+           break;
+       }
+      if (msgstr == NULL)
+       {
+         if (p + strlen (p) + 1 >= p_end)
+           {
+             /* Remove the string that starts at p.  */
+             mp->msgstr_len = p - mp->msgstr;
+             return;
+           }
+         /* It is not possible to remove an element of the string list
+            except the last one.  So just replace it with the empty string.
+            That's the best we can do here.  */
+         msgstr = "";
+       }
+      {
+       /* Replace the string that starts at p.  */
+       size_t i1 = p - mp->msgstr;
+       size_t i2before = i1 + strlen (p);
+       size_t i2after = i1 + strlen (msgstr);
+       size_t new_msgstr_len = mp->msgstr_len - i2before + i2after;
+
+       if (i2after > i2before)
+         mp->msgstr = (char *) xrealloc ((char *) mp->msgstr, new_msgstr_len);
+       memmove ((char *) mp->msgstr + i2after, mp->msgstr + i2before,
+                mp->msgstr_len - i2before);
+       memcpy ((char *) mp->msgstr + i1, msgstr, i2after - i1);
+       mp->msgstr_len = new_msgstr_len;
+      }
+      if (copied_msgstr != NULL)
+       free (copied_msgstr);
+    }
+}
+
+
+/* Return the comments for a message.  */
+
+const char *
+po_message_comments (po_message_t message)
+{
+  /* FIXME: memory leak.  */
+  message_ty *mp = (message_ty *) message;
+
+  if (mp->comment == NULL || mp->comment->nitems == 0)
+    return "";
+  else
+    return string_list_join (mp->comment, '\n', '\n', true);
+}
+
+
+/* Change the comments for a message.
+   comments should be a multiline string, ending in a newline, or empty.  */
+
+void
+po_message_set_comments (po_message_t message, const char *comments)
+{
+  message_ty *mp = (message_ty *) message;
+  string_list_ty *slp = string_list_alloc ();
+
+  {
+    char *copy = xstrdup (comments);
+    char *rest;
+
+    rest = copy;
+    while (*rest != '\0')
+      {
+       char *newline = strchr (rest, '\n');
+
+       if (newline != NULL)
+         {
+           *newline = '\0';
+           string_list_append (slp, rest);
+           rest = newline + 1;
+         }
+       else
+         {
+           string_list_append (slp, rest);
+           break;
+         }
+      }
+    free (copy);
+  }
+
+  if (mp->comment != NULL)
+    string_list_free (mp->comment);
+
+  mp->comment = slp;
+}
+
+
+/* Return the extracted comments for a message.  */
+
+const char *
+po_message_extracted_comments (po_message_t message)
+{
+  /* FIXME: memory leak.  */
+  message_ty *mp = (message_ty *) message;
+
+  if (mp->comment_dot == NULL || mp->comment_dot->nitems == 0)
+    return "";
+  else
+    return string_list_join (mp->comment_dot, '\n', '\n', true);
+}
+
+
+/* Return the i-th file position for a message, or NULL if i is out of
+   range.  */
+
+po_filepos_t
+po_message_filepos (po_message_t message, int i)
+{
+  message_ty *mp = (message_ty *) message;
+
+  if (i >= 0 && (size_t)i < mp->filepos_count)
+    return (po_filepos_t) &mp->filepos[i];
+  else
+    return NULL;
+}
+
+
 /* Return true if the message is marked obsolete.  */
 
 int
@@ -291,6 +635,17 @@ po_message_is_obsolete (po_message_t message)
 }
 
 
+/* Change the obsolete mark of a message.  */
+
+void
+po_message_set_obsolete (po_message_t message, int obsolete)
+{
+  message_ty *mp = (message_ty *) message;
+
+  mp->obsolete = obsolete;
+}
+
+
 /* Return true if the message is marked fuzzy.  */
 
 int
@@ -302,6 +657,17 @@ po_message_is_fuzzy (po_message_t message)
 }
 
 
+/* Change the fuzzy mark of a message.  */
+
+void
+po_message_set_fuzzy (po_message_t message, int fuzzy)
+{
+  message_ty *mp = (message_ty *) message;
+
+  mp->is_fuzzy = fuzzy;
+}
+
+
 /* Return true if the message is marked as being a format string of the given
    type (e.g. "c-format").  */
 
@@ -320,3 +686,57 @@ po_message_is_format (po_message_t message, const char *format_type)
        return (possible_format_p (mp->is_format[i]) ? 1 : 0);
   return 0;
 }
+
+
+/* Change the format string mark for a given type of a message.  */
+
+void
+po_message_set_format (po_message_t message, const char *format_type, /*bool*/int value)
+{
+  message_ty *mp = (message_ty *) message;
+  size_t len = strlen (format_type);
+  size_t i;
+
+  if (len >= 7 && memcmp (format_type + len - 7, "-format", 7) == 0)
+    for (i = 0; i < NFORMATS; i++)
+      if (strlen (format_language[i]) == len - 7
+         && memcmp (format_language[i], format_type, len - 7) == 0)
+       /* The given format_type corresponds to (enum format_type) i.  */
+       mp->is_format[i] = (value ? yes : no);
+}
+
+
+#if 0
+/* Test whether the message translation is a valid format string if the message
+   is marked as being a format string.  Return NULL if valid or not marked as
+   such, or an explanation string if invalid.  */
+
+char *
+po_message_check_format (po_message_t message, const char *format_type)
+{
+  ??
+}
+#endif
+
+
+/* Return the file name.  */
+
+const char *
+po_filepos_file (po_filepos_t filepos)
+{
+  lex_pos_ty *pp = (lex_pos_ty *) filepos;
+
+  return pp->file_name;
+}
+
+
+/* Return the line number where the string starts, or (size_t)(-1) if no line
+   number is available.  */
+
+size_t
+po_filepos_start_line (po_filepos_t filepos)
+{
+  lex_pos_ty *pp = (lex_pos_ty *) filepos;
+
+  return pp->line_number;
+}
index 875352270d518966f51fd777aa8ad6e6816efd7d..e735652aec3ee8c55157f1201de011f1efa494cc 100644 (file)
@@ -1,5 +1,5 @@
 /* Public API for GNU gettext PO files - contained in libgettextpo.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.
 
    This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,8 @@
 #ifndef _GETTEXT_PO_H
 #define _GETTEXT_PO_H 1
 
+#include <stdlib.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -36,6 +38,40 @@ 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;
 
+/* A po_filepos_t represents a string's position within a source file.  */
+typedef struct po_filepos *po_filepos_t;
+
+/* A po_error_handler handles error situations.  */
+struct po_error_handler
+{
+  /* Signal an error.  The error message is built from FORMAT and the following
+     arguments.  ERRNUM, if nonzero, is an errno value.
+     Must increment the error_message_count variable declared in error.h.
+     Must not return if STATUS is nonzero.  */
+  void (*error) (int status, int errnum,
+                const char *format, ...);
+
+  /* Signal an error.  The error message is built from FORMAT and the following
+     arguments.  The error location is at FILENAME line LINENO. ERRNUM, if
+     nonzero, is an errno value.
+     Must increment the error_message_count variable declared in error.h.
+     Must not return if STATUS is nonzero.  */
+  void (*error_at_line) (int status, int errnum,
+                        const char *filename, unsigned int lineno,
+                        const char *format, ...);
+
+  /* Signal a multiline warning.  The PREFIX applies to all lines of the
+     MESSAGE.  Free the PREFIX and MESSAGE when done.  */
+  void (*multiline_warning) (char *prefix, char *message);
+
+  /* Signal a multiline error.  The PREFIX applies to all lines of the
+     MESSAGE.  Free the PREFIX and MESSAGE when done.
+     Must increment the error_message_count variable declared in error.h if
+     PREFIX is non-NULL.  */
+  void (*multiline_error) (char *prefix, char *message);
+};
+typedef const struct po_error_handler *po_error_handler_t;
+
 /* Memory allocation:
    The memory allocations performed by these functions use xmalloc(),
    therefore will cause a program exit if memory is exhausted.
@@ -45,9 +81,19 @@ typedef struct po_message *po_message_t;
 
 /* ============================= po_file_t API ============================= */
 
+/* Create an empty PO file representation in memory.  */
+extern po_file_t po_file_create (void);
+
 /* 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);
+#define po_file_read po_file_read_v2
+extern po_file_t po_file_read (const char *filename,
+                              po_error_handler_t handler);
+
+/* Write an in-memory PO file to a file.
+   Upon failure, return NULL and set errno.  */
+extern po_file_t po_file_write (po_file_t file, const char *filename,
+                               po_error_handler_t handler);
 
 /* Free a PO file from memory.  */
 extern void po_file_free (po_file_t file);
@@ -82,34 +128,98 @@ extern void po_message_iterator_free (po_message_iterator_t iterator);
    Return NULL at the end of the message list.  */
 extern po_message_t po_next_message (po_message_iterator_t iterator);
 
+/* Insert a message in a PO file in memory, in the domain and at the position
+   indicated by the iterator.  The iterator thereby advances past the freshly
+   inserted message.  */
+extern void po_message_insert (po_message_iterator_t iterator, po_message_t message);
+
 
 /* =========================== po_message_t API ============================ */
 
+/* Return a freshly constructed message.
+   To finish initializing the message, you must set the msgid and msgstr.  */
+extern po_message_t po_message_create (void);
+
 /* Return the msgid (untranslated English string) of a message.  */
 extern const char * po_message_msgid (po_message_t message);
 
+/* Change the msgid (untranslated English string) of a message.  */
+extern void po_message_set_msgid (po_message_t message, const char *msgid);
+
 /* 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);
 
+/* Change the msgid_plural (untranslated English plural string) of a message.
+   NULL means a message without plural.  */
+extern void po_message_set_msgid_plural (po_message_t message, const char *msgid_plural);
+
 /* 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);
 
+/* Change the msgstr (translation) of a message.
+   Use an empty string to denote an untranslated message.  */
+extern void po_message_set_msgstr (po_message_t message, const char *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.  */
 extern const char * po_message_msgstr_plural (po_message_t message, int index);
 
+/* Change the msgstr[index] for a message with plural handling.
+   Use a NULL value at the end to reduce the number of plural forms.  */
+extern void po_message_set_msgstr_plural (po_message_t message, int index, const char *msgstr);
+
+/* Return the comments for a message.  */
+extern const char * po_message_comments (po_message_t message);
+
+/* Change the comments for a message.
+   comments should be a multiline string, ending in a newline, or empty.  */
+extern void po_message_set_comments (po_message_t message, const char *comments);
+
+/* Return the extracted comments for a message.  */
+extern const char * po_message_extracted_comments (po_message_t message);
+
+/* Return the i-th file position for a message, or NULL if i is out of
+   range.  */
+extern po_filepos_t po_message_filepos (po_message_t message, int i);
+
 /* Return true if the message is marked obsolete.  */
 extern int po_message_is_obsolete (po_message_t message);
 
+/* Change the obsolete mark of a message.  */
+extern void po_message_set_obsolete (po_message_t message, int obsolete);
+
 /* Return true if the message is marked fuzzy.  */
 extern int po_message_is_fuzzy (po_message_t message);
 
+/* Change the fuzzy mark of a message.  */
+extern void po_message_set_fuzzy (po_message_t message, int fuzzy);
+
 /* Return true if the message is marked as being a format string of the given
    type (e.g. "c-format").  */
 extern int po_message_is_format (po_message_t message, const char *format_type);
 
+/* Change the format string mark for a given type of a message.  */
+extern void po_message_set_format (po_message_t message, const char *format_type, /*bool*/int value);
+
+#if 0
+/* Test whether the message translation is a valid format string if the message
+   is marked as being a format string.  Return NULL if valid or not marked as
+   such, or an explanation string if invalid.  */
+extern char * po_message_check_format (po_message_t message, const char *format_type);
+#endif
+
+
+/* =========================== po_filepos_t API ============================ */
+
+/* Return the file name.  */
+extern const char * po_filepos_file (po_filepos_t filepos);
+
+/* Return the line number where the string starts, or (size_t)(-1) if no line
+   number is available.  */
+extern size_t po_filepos_start_line (po_filepos_t filepos);
+
 
 #ifdef __cplusplus
 }
index 94a4be6a7662960e95d5be0291509860941f9153..c75aa16eb3eb07dc0e4e365fdcef14f9fd8036c7 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -290,6 +290,32 @@ message_list_prepend (message_list_ty *mlp, message_ty *mp)
 }
 
 
+void
+message_list_insert_at (message_list_ty *mlp, size_t n, message_ty *mp)
+{
+  size_t j;
+
+  if (mlp->nitems >= mlp->nitems_max)
+    {
+      size_t nbytes;
+
+      mlp->nitems_max = mlp->nitems_max * 2 + 4;
+      nbytes = mlp->nitems_max * sizeof (message_ty *);
+      mlp->item = xrealloc (mlp->item, nbytes);
+    }
+  for (j = mlp->nitems; j > n; j--)
+    mlp->item[j] = mlp->item[j - 1];
+  mlp->item[j] = mp;
+  mlp->nitems++;
+
+  if (mlp->use_hashtable)
+    if (insert_entry (&mlp->htable, mp->msgid, strlen (mp->msgid) + 1, mp))
+      /* A message list has duplicates, although it was allocated with the
+        assertion that it wouldn't have duplicates.  It is a bug.  */
+      abort ();
+}
+
+
 #if 0 /* unused */
 void
 message_list_delete_nth (message_list_ty *mlp, size_t n)
index 33a6dacc1e4c8708ea471e6cc4adee67ff428f40..ebbb848e6a07254edd5267491c7698cc599738c7 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -191,6 +191,8 @@ extern void
        message_list_append (message_list_ty *mlp, message_ty *mp);
 extern void
        message_list_prepend (message_list_ty *mlp, message_ty *mp);
+extern void
+       message_list_insert_at (message_list_ty *mlp, size_t n, message_ty *mp);
 extern void
        message_list_delete_nth (message_list_ty *mlp, size_t n);
 typedef bool message_predicate_ty (const message_ty *mp);
index 4399a8607965e8ff52567a93fbbae4d5e1b5271c..ec7906d7a6636c42a176769afa41841f2395a3d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Charset handling while reading PO files.
-   Copyright (C) 2001-2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 
    This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
 
 #include "xallocsa.h"
 #include "xerror.h"
+#include "po-error.h"
 #include "basename.h"
 #include "progname.h"
 #include "strstr.h"
@@ -222,11 +223,11 @@ po_lex_charset_set (const char *header_entry, const char *filename)
          if (!(filenamelen >= 4
                && memcmp (filename + filenamelen - 4, ".pot", 4) == 0
                && strcmp (charset, "CHARSET") == 0))
-           multiline_warning (xasprintf (_("%s: warning: "), filename),
-                              xasprintf (_("\
+           po_multiline_warning (xasprintf (_("%s: warning: "), filename),
+                                 xasprintf (_("\
 Charset \"%s\" is not a portable encoding name.\n\
 Message conversion to user's charset might not work.\n"),
-                                         charset));
+                                            charset));
        }
       else
        {
@@ -292,22 +293,22 @@ Message conversion to user's charset might not work.\n"),
                  else
                    note = _("Continuing anyway.");
 
-                 multiline_warning (xasprintf (_("%s: warning: "), filename),
-                                    xasprintf (_("\
+                 po_multiline_warning (xasprintf (_("%s: warning: "), filename),
+                                       xasprintf (_("\
 Charset \"%s\" is not supported. %s relies on iconv(),\n\
 and iconv() does not support \"%s\".\n"),
-                                               po_lex_charset,
-                                               basename (program_name),
-                                               po_lex_charset));
+                                                  po_lex_charset,
+                                                  basename (program_name),
+                                                  po_lex_charset));
 
 # if !defined _LIBICONV_VERSION
-                 multiline_warning (NULL,
-                                    xasprintf (_("\
+                 po_multiline_warning (NULL,
+                                       xasprintf (_("\
 Installing GNU libiconv and then reinstalling GNU gettext\n\
 would fix this problem.\n")));
 # endif
 
-                 multiline_warning (NULL, xasprintf (_("%s\n"), note));
+                 po_multiline_warning (NULL, xasprintf (_("%s\n"), note));
                }
 #else
              /* Test for a charset which has double-byte characters
@@ -320,19 +321,19 @@ would fix this problem.\n")));
                  const char *note =
                    _("Continuing anyway, expect parse errors.");
 
-                 multiline_warning (xasprintf (_("%s: warning: "), filename),
-                                    xasprintf (_("\
+                 po_multiline_warning (xasprintf (_("%s: warning: "), filename),
+                                       xasprintf (_("\
 Charset \"%s\" is not supported. %s relies on iconv().\n\
 This version was built without iconv().\n"),
-                                               po_lex_charset,
-                                               basename (program_name)));
+                                                  po_lex_charset,
+                                                  basename (program_name)));
 
-                 multiline_warning (NULL,
-                                    xasprintf (_("\
+                 po_multiline_warning (NULL,
+                                       xasprintf (_("\
 Installing GNU libiconv and then reinstalling GNU gettext\n\
 would fix this problem.\n")));
 
-                 multiline_warning (NULL, xasprintf (_("%s\n"), note));
+                 po_multiline_warning (NULL, xasprintf (_("%s\n"), note));
                }
 #endif
            }
@@ -347,8 +348,8 @@ would fix this problem.\n")));
 
       if (!(filenamelen >= 4
            && memcmp (filename + filenamelen - 4, ".pot", 4) == 0))
-       multiline_warning (xasprintf (_("%s: warning: "), filename),
-                          xasprintf (_("\
+       po_multiline_warning (xasprintf (_("%s: warning: "), filename),
+                             xasprintf (_("\
 Charset missing in header.\n\
 Message conversion to user's charset will not work.\n")));
     }
index 8a55978274cd87285b01db0fc5d8784ad944a478..1da40f9085f3ccc0dbd489a0ff4163f88692a776 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>.
    Multibyte character handling by Bruno Haible <haible@clisp.cons.org>.
@@ -89,8 +89,8 @@ po_gram_error (const char *fmt, ...)
     error (EXIT_FAILURE, 0, _("memory exhausted"));
   va_end (ap);
   error_with_progname = false;
-  error (0, 0, "%s:%lu:%d: %s", gram_pos.file_name,
-        (unsigned long) gram_pos.line_number, gram_pos_column + 1, buffer);
+  po_error (0, 0, "%s:%lu:%d: %s", gram_pos.file_name,
+           (unsigned long) gram_pos.line_number, gram_pos_column + 1, buffer);
   error_with_progname = true;
   free (buffer);
 
@@ -100,7 +100,7 @@ po_gram_error (const char *fmt, ...)
   if (*fmt == '.')
     --error_message_count;
   else if (error_message_count >= gram_max_allowed_errors)
-    error (EXIT_FAILURE, 0, _("too many errors, aborting"));
+    po_error (EXIT_FAILURE, 0, _("too many errors, aborting"));
 }
 
 /* CAUTION: If you change this function, you must also make identical
@@ -118,7 +118,7 @@ po_gram_error_at_line (const lex_pos_ty *pp, const char *fmt, ...)
     error (EXIT_FAILURE, 0, _("memory exhausted"));
   va_end (ap);
   error_with_progname = false;
-  error_at_line (0, 0, pp->file_name, pp->line_number, "%s", buffer);
+  po_error_at_line (0, 0, pp->file_name, pp->line_number, "%s", buffer);
   error_with_progname = true;
   free (buffer);
 
@@ -129,7 +129,7 @@ po_gram_error_at_line (const lex_pos_ty *pp, const char *fmt, ...)
   if (*fmt == '.')
     --error_message_count;
   else if (error_message_count >= gram_max_allowed_errors)
-    error (EXIT_FAILURE, 0, _("too many errors, aborting"));
+    po_error (EXIT_FAILURE, 0, _("too many errors, aborting"));
 }
 
 #endif
@@ -501,7 +501,7 @@ incomplete multibyte sequence at end of line"));
                    }
                }
              else
-               error (EXIT_FAILURE, errno, _("iconv failure"));
+               po_error (EXIT_FAILURE, errno, _("iconv failure"));
            }
          else
            {
@@ -663,8 +663,8 @@ lex_getc (mbchar_t mbc)
          if (ferror (mbf->fp))
            {
            bomb:
-             error (EXIT_FAILURE, errno, _("error while reading \"%s\""),
-                    gram_pos.file_name);
+             po_error (EXIT_FAILURE, errno, _("error while reading \"%s\""),
+                       gram_pos.file_name);
            }
          break;
        }
index 12ee225288f27f7c37ed880f949532adb9b5f790..10533e0aba9fb2c6d57b9911809c83115f1252e0 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -25,8 +25,9 @@
 #include <stdbool.h>
 #include "error.h"
 #include "error-progname.h"
-#include "pos.h"
 #include "xerror.h"
+#include "po-error.h"
+#include "pos.h"
 
 
 #ifdef __cplusplus
@@ -81,15 +82,15 @@ extern void po_lex_pass_obsolete_entries (bool flag);
   do {                                                                     \
     char *totalfmt = xasprintf ("%s%s", "%s:%lu:%d: ", fmt);               \
     error_with_progname = false;                                           \
-    error (0, 0, totalfmt, gram_pos.file_name,                             \
-          (unsigned long) gram_pos.line_number, gram_pos_column + 1,       \
-          __VA_ARGS__ + 0);                                                \
+    po_error (0, 0, totalfmt, gram_pos.file_name,                          \
+             (unsigned long) gram_pos.line_number, gram_pos_column + 1,    \
+             __VA_ARGS__ + 0);                                             \
     error_with_progname = true;                                                    \
     free (totalfmt);                                                       \
     if (*fmt == '.')                                                       \
       --error_message_count;                                               \
     else if (error_message_count >= gram_max_allowed_errors)               \
-      error (1, 0, _("too many errors, aborting"));                        \
+      po_error (1, 0, _("too many errors, aborting"));                     \
   } while (0)
 
 /* CAUTION: If you change this macro, you must also make identical
@@ -98,13 +99,13 @@ extern void po_lex_pass_obsolete_entries (bool flag);
 # define po_gram_error_at_line(pos, fmt, ...)                              \
   do {                                                                     \
     error_with_progname = false;                                           \
-    error_at_line (0, 0, (pos)->file_name, (pos)->line_number,             \
-                  fmt, __VA_ARGS__ + 0);                                   \
+    po_error_at_line (0, 0, (pos)->file_name, (pos)->line_number,          \
+                     fmt, __VA_ARGS__ + 0);                                \
     error_with_progname = true;                                                    \
     if (*fmt == '.')                                                       \
       --error_message_count;                                               \
     else if (error_message_count >= gram_max_allowed_errors)               \
-      error (1, 0, _("too many errors, aborting"));                        \
+      po_error (1, 0, _("too many errors, aborting"));                     \
   } while (0)
 
 /* GCC is also smart enough to allow optimizations like this.  */
@@ -117,14 +118,14 @@ extern void po_lex_pass_obsolete_entries (bool flag);
   do {                                                                     \
     char *totalfmt = xasprintf ("%s%s", "%s:%d:%d: ", fmt);                \
     error_with_progname = false;                                           \
-    error (0, 0, totalfmt, gram_pos.file_name, gram_pos.line_number,       \
-          gram_pos_column + 1 , ## args);                                  \
+    po_error (0, 0, totalfmt, gram_pos.file_name, gram_pos.line_number,            \
+             gram_pos_column + 1 , ## args);                               \
     error_with_progname = true;                                                    \
     free (totalfmt);                                                       \
     if (*fmt == '.')                                                       \
       --error_message_count;                                               \
     else if (error_message_count >= gram_max_allowed_errors)               \
-      error (1, 0, _("too many errors, aborting"));                        \
+      po_error (1, 0, _("too many errors, aborting"));                     \
   } while (0)
 
 /* CAUTION: If you change this macro, you must also make identical
@@ -133,13 +134,13 @@ extern void po_lex_pass_obsolete_entries (bool flag);
 # define po_gram_error_at_line(pos, fmt, args...)                          \
   do {                                                                     \
     error_with_progname = false;                                           \
-    error_at_line (0, 0, (pos)->file_name, (pos)->line_number,             \
-                   fmt , ## args);                                         \
+    po_error_at_line (0, 0, (pos)->file_name, (pos)->line_number,          \
+                     fmt , ## args);                                       \
     error_with_progname = true;                                                    \
     if (*fmt == '.')                                                       \
       --error_message_count;                                               \
     else if (error_message_count >= gram_max_allowed_errors)               \
-      error (1, 0, _("too many errors, aborting"));                        \
+      po_error (1, 0, _("too many errors, aborting"));                     \
   } while (0)
 
 #else
index 0aa1300f533718d921548fb44662442c914e370f..1230a951b6dcdcfd036988fd763ea7184ece2ef6 100644 (file)
@@ -1,5 +1,5 @@
 /* Reading PO files, abstract class.
-   Copyright (C) 1995-1996, 1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1996, 1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -188,10 +188,10 @@ po_scan (abstract_po_reader_ty *pop, FILE *fp,
     }
 
   if (error_message_count > 0)
-    error (EXIT_FAILURE, 0,
-          ngettext ("found %d fatal error", "found %d fatal errors",
-                    error_message_count),
-          error_message_count);
+    po_error (EXIT_FAILURE, 0,
+             ngettext ("found %d fatal error", "found %d fatal errors",
+                       error_message_count),
+             error_message_count);
   error_message_count = 0;
 }
 
index fb324432626a08681225a208e80403af0e0af31d..bcf14beb5447d7e5e3bc5a7a9bd74c0e146bffb0 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995, 1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -176,11 +176,14 @@ string_list_concat_destroy (string_list_ty *slp)
 }
 
 
-#if 0 /* unused */
 /* Return a freshly allocated string obtained by concatenating all the
-   strings in the list, separated by spaces.  */
+   strings in the list, separated by the separator character, terminated
+   by the terminator character.  The terminator character is not added if
+   drop_redundant_terminator is true and the last string already ends with
+   the terminator. */
 char *
-string_list_join (const string_list_ty *slp)
+string_list_join (const string_list_ty *slp, char separator,
+                 char terminator, bool drop_redundant_terminator)
 {
   size_t len;
   size_t j;
@@ -190,24 +193,31 @@ string_list_join (const string_list_ty *slp)
   len = 1;
   for (j = 0; j < slp->nitems; ++j)
     {
-      if (j)
+      if (separator && j > 0)
        ++len;
       len += strlen (slp->item[j]);
     }
+  if (terminator)
+    ++len;
   result = (char *) xmalloc (len);
   pos = 0;
   for (j = 0; j < slp->nitems; ++j)
     {
-      if (j)
-       result[pos++] = ' ';
+      if (separator && j > 0)
+       result[pos++] = separator;
       len = strlen (slp->item[j]);
       memcpy (result + pos, slp->item[j], len);
       pos += len;
     }
+  if (terminator
+      && !(drop_redundant_terminator
+          && slp->nitems > 0
+          && (len = strlen (slp->item[slp->nitems - 1])) > 0
+          && slp->item[slp->nitems - 1][len - 1] == terminator))
+    result[pos++] = terminator;
   result[pos] = '\0';
   return result;
 }
-#endif
 
 
 /* Return 1 if s is contained in the list of strings, 0 otherwise.  */
index f316c9729182e3d6e1c92a96711cb2609cdb9fce..0787ebe3458afb3bc08d3d72280b93782b5e1b04 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1996, 1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1996, 1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -69,11 +69,13 @@ extern char *string_list_concat (const string_list_ty *slp);
    strings in the list, and destroy the list.  */
 extern char *string_list_concat_destroy (string_list_ty *slp);
 
-#if 0 /* unused */
 /* Return a freshly allocated string obtained by concatenating all the
-   strings in the list, separated by spaces.  */
-extern char *string_list_join (const string_list_ty *slp);
-#endif
+   strings in the list, separated by the separator character, terminated
+   by the terminator character.  The terminator character is not added if
+   drop_redundant_terminator is true and the last string already ends with
+   the terminator. */
+extern char *string_list_join (const string_list_ty *slp, char separator,
+                              char terminator, bool drop_redundant_terminator);
 
 /* Return 1 if s is contained in the list of strings, 0 otherwise.  */
 extern bool string_list_member (const string_list_ty *slp, const char *s);
index 201aa38b6449233745f38339f7c3ddae04635dfd..01dd0ff228190fcdd7831d98b600fef04c2f862e 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -47,8 +47,8 @@
 #include "fwriteerror.h"
 #include "exit.h"
 #include "error-progname.h"
-#include "error.h"
 #include "xerror.h"
+#include "po-error.h"
 #include "gettext.h"
 
 /* Our regular abbreviation.  */
@@ -552,7 +552,7 @@ wrap (FILE *fp, const char *line_prefix, const char *name, const char *value,
                    {
                      if (errno == EILSEQ)
                        {
-                         error (0, 0, _("invalid multibyte sequence"));
+                         po_error (0, 0, _("invalid multibyte sequence"));
                          continue;
                        }
                      else
@@ -603,9 +603,9 @@ wrap (FILE *fp, const char *line_prefix, const char *name, const char *value,
              /* We warn about any use of escape sequences beside
                 '\n' and '\t'.  */
              if (c != 'n' && c != 't')
-               error (0, 0, _("\
+               po_error (0, 0, _("\
 internationalized messages should not contain the `\\%c' escape sequence"),
-                      c);
+                         c);
            }
          else if (escape && !c_isprint ((unsigned char) c))
            {
@@ -658,7 +658,7 @@ internationalized messages should not contain the `\\%c' escape sequence"),
                    {
                      if (errno == EILSEQ)
                        {
-                         error (0, 0, _("invalid multibyte sequence"));
+                         po_error (0, 0, _("invalid multibyte sequence"));
                          continue;
                        }
                      else
@@ -848,8 +848,8 @@ message_print (const message_ty *mp, FILE *fp, const char *charset,
      this domain, emit an empty string.  */
   if (!is_ascii_string (mp->msgid)
       && po_charset_canonicalize (charset) != po_charset_utf8)
-    multiline_warning (xasprintf (_("warning: ")),
-                      xasprintf (_("\
+    po_multiline_warning (xasprintf (_("warning: ")),
+                         xasprintf (_("\
 The following msgid contains non-ASCII characters.\n\
 This will cause problems to translators who use a character encoding\n\
 different from yours. Consider using a pure ASCII msgid instead.\n\
@@ -914,8 +914,8 @@ message_print_obsolete (const message_ty *mp, FILE *fp, const char *charset,
      are as readable as possible.  */
   if (!is_ascii_string (mp->msgid)
       && po_charset_canonicalize (charset) != po_charset_utf8)
-    multiline_warning (xasprintf (_("warning: ")),
-                      xasprintf (_("\
+    po_multiline_warning (xasprintf (_("warning: ")),
+                         xasprintf (_("\
 The following msgid contains non-ASCII characters.\n\
 This will cause problems to translators who use a character encoding\n\
 different from yours. Consider using a pure ASCII msgid instead.\n\
@@ -1060,9 +1060,9 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename,
       if (mdlp->nitems > 1)
        {
          if (use_syntax_properties)
-           error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with Java .properties syntax. Try using PO file syntax instead."));
+           po_error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with Java .properties syntax. Try using PO file syntax instead."));
          if (use_syntax_stringtable)
-           error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with NeXTstep/GNUstep .strings syntax."));
+           po_error (EXIT_FAILURE, 0, _("Cannot output multiple translation domains into a single file with NeXTstep/GNUstep .strings syntax."));
        }
       if (mdlp->nitems == 1)
        {
@@ -1086,13 +1086,13 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename,
            {
              error_with_progname = false;
              if (use_syntax_properties)
-               error_at_line (EXIT_FAILURE, 0,
-                              has_plural->file_name, has_plural->line_number,
-                              _("message catalog has plural form translations, but the output format does not support them. Try generating a Java class using \"msgfmt --java\", instead of a properties file."));
+               po_error_at_line (EXIT_FAILURE, 0,
+                                 has_plural->file_name, has_plural->line_number,
+                                 _("message catalog has plural form translations, but the output format does not support them. Try generating a Java class using \"msgfmt --java\", instead of a properties file."));
              if (use_syntax_stringtable)
-               error_at_line (EXIT_FAILURE, 0,
-                              has_plural->file_name, has_plural->line_number,
-                              _("message catalog has plural form translations, but the output format does not support them."));
+               po_error_at_line (EXIT_FAILURE, 0,
+                                 has_plural->file_name, has_plural->line_number,
+                                 _("message catalog has plural form translations, but the output format does not support them."));
              error_with_progname = true;
            }
        }
@@ -1104,8 +1104,8 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename,
     {
       fp = fopen (filename, "w");
       if (fp == NULL)
-       error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""),
-              filename);
+       po_error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""),
+                 filename);
     }
   else
     {
@@ -1123,8 +1123,8 @@ msgdomain_list_print (msgdomain_list_ty *mdlp, const char *filename,
 
   /* Make sure nothing went wrong.  */
   if (fwriteerror (fp))
-    error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"),
-          filename);
+    po_error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"),
+             filename);
 
   if (fp != stdout)
     fclose (fp);
index 1dfb2d61fa31bc3897ebb6cebdaf8b3912c4faad..a5440699ef0aeca3447d2fffd7b0526c9c20f798 100644 (file)
@@ -1,10 +1,20 @@
 LIBRARY gettextpo
 EXPORTS
+po_file_create
 po_file_domains
 po_file_domain_header
 po_file_free
 po_file_read
+po_file_read_v2
+po_file_write
+po_filepos_file
+po_filepos_start_line
 po_header_field
+po_message_comments
+po_message_create
+po_message_extracted_comments
+po_message_filepos
+po_message_insert
 po_message_is_format
 po_message_is_fuzzy
 po_message_is_obsolete
@@ -14,4 +24,12 @@ po_message_msgid
 po_message_msgid_plural
 po_message_msgstr
 po_message_msgstr_plural
+po_message_set_comments
+po_message_set_format
+po_message_set_fuzzy
+po_message_set_msgid
+po_message_set_msgid_plural
+po_message_set_msgstr
+po_message_set_msgstr_plural
+po_message_set_obsolete
 po_next_message
index 008620b9df129cfd42693147d004370032ce5819..e10c2477870f802b024f1ed775405bf7a6aa6021 100644 (file)
@@ -35,10 +35,14 @@ plural_table
 plural_table_size
 po_charset_ascii
 po_charset_utf8
+po_error
+po_error_at_line
 po_gram_lval
 po_lex_charset
 po_lex_iconv
 po_lex_weird_cjk
+po_multiline_error
+po_multiline_warning
 use_first
 catenate_msgdomain_list
 compare_po_locale_charsets