]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Support for the 'I' flag that translators can use in messages marked
authorBruno Haible <bruno@clisp.org>
Thu, 15 Jan 2004 11:36:37 +0000 (11:36 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:38 +0000 (12:11 +0200)
as 'c-format'.

32 files changed:
NEWS
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/gmo.h
gettext-runtime/intl/loadmsgcat.c
gettext-tools/doc/ChangeLog
gettext-tools/doc/gettext.texi
gettext-tools/src/ChangeLog
gettext-tools/src/format-awk.c
gettext-tools/src/format-c.c
gettext-tools/src/format-csharp.c
gettext-tools/src/format-elisp.c
gettext-tools/src/format-gcc-internal.c
gettext-tools/src/format-java.c
gettext-tools/src/format-librep.c
gettext-tools/src/format-lisp.c
gettext-tools/src/format-pascal.c
gettext-tools/src/format-perl-brace.c
gettext-tools/src/format-perl.c
gettext-tools/src/format-php.c
gettext-tools/src/format-python.c
gettext-tools/src/format-qt.c
gettext-tools/src/format-sh.c
gettext-tools/src/format-tcl.c
gettext-tools/src/format-ycp.c
gettext-tools/src/format.h
gettext-tools/src/msgfmt.c
gettext-tools/src/msgmerge.c
gettext-tools/src/read-mo.c
gettext-tools/src/write-mo.c
gettext-tools/src/xgettext.c
gettext-tools/tests/ChangeLog
gettext-tools/tests/Makefile.am

diff --git a/NEWS b/NEWS
index 48496b2ddc319c5ec89e2942cad3880fd45839bb..16f919820286d231e1a919dd0cbbbba0264478a6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,11 @@ Version 0.14 - January 2004
 
     msgfmt can create (and msgunfmt can dump) message catalogs for C#.
 
+* Special feature for Farsi (Persian): Translators can insert an 'I' flag
+  into numeric format directives in format strings. Its effect is that, on
+  glibc systems, the number is generated with the locale dependent set of
+  special digits instead of the usual ASCII digits.
+
 * Documentation:
 
   - New documentation section: C#.
index ef1f0d94505b634de4986fc05a8657660460230c..56c1449a84a915aa10ea414bc8e51b2a303c126d 100644 (file)
@@ -1,3 +1,9 @@
+2004-01-09  Bruno Haible  <bruno@clisp.org>
+
+       * gmo.h (MO_REVISION_NUMBER_WITH_SYSDEP_I): New definition.
+       * loadmsgcat.c (get_sysdep_segment_value): Handle "I".
+       (_nl_load_domain): Treat major revision 1 like major revision 0.
+
 2004-01-08  Bruno Haible  <bruno@clisp.org>
 
        * loadmsgcat.c (_nl_load_domain): When a string pair uses a system
index d1fe4d6b8fd4a23eac6a13b8cd6114629d7c1ffe..e7c9cc14b5d6d556559f6ea54259b1640c48f79d 100644 (file)
@@ -1,5 +1,5 @@
 /* Description of GNU message catalog format: general file layout.
-   Copyright (C) 1995, 1997, 2000-2002 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997, 2000-2002, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published
@@ -29,6 +29,7 @@
 
 /* Revision number of the currently used .mo (binary) file format.  */
 #define MO_REVISION_NUMBER 0
+#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1
 
 /* The following contortions are an attempt to use the C preprocessor
    to determine an unsigned integral type that is 32 bits wide.  An
@@ -76,7 +77,7 @@ struct mo_file_header
   /* The revision number of the file format.  */
   nls_uint32 revision;
 
-  /* The following are only used in .mo files with major revision 0.  */
+  /* The following are only used in .mo files with major revision 0 or 1.  */
 
   /* The number of strings pairs.  */
   nls_uint32 nstrings;
index 5d658538a62cdcb8cec54d9490d8d1389f996c29..99c51b4c5c2f69e719926ea311093738be42e563 100644 (file)
@@ -748,6 +748,18 @@ get_sysdep_segment_value (const char *name)
            }
        }
     }
+  /* Test for a glibc specific printf() format directive flag.  */
+  if (name[0] == 'I' && name[1] == '\0')
+    {
+#if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+      /* The 'I' flag, in numeric format directives, replaces ASCII digits
+        with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
+        used for Farsi (Persian) and maybe Arabic.  */
+      return "I";
+#else
+      return "";
+#endif
+    }
   /* Other system dependent strings are not valid.  */
   return NULL;
 }
@@ -1019,10 +1031,11 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
 
   /* Fill in the information about the available tables.  */
   revision = W (domain->must_swap, data->revision);
-  /* We support only the major revision 0.  */
+  /* We support only the major revisions 0 and 1.  */
   switch (revision >> 16)
     {
     case 0:
+    case 1:
       domain->nstrings = W (domain->must_swap, data->nstrings);
       domain->orig_tab = (const struct string_desc *)
        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
index fc983d5e2da1c0e91e9cebcd14fb870a41c2cdf1..e6ef3e5fe757081b421ccf360f517a97887aa317 100644 (file)
@@ -1,3 +1,7 @@
+2004-01-09  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.texi (c-format): Document the 'I' flag.
+
 2004-01-14  Bruno Haible  <bruno@clisp.org>
 
        * gettext.texi: Add entrypoints for ngettext and envsubst.
index 78554088452e0b2e777843e55b816bc3276db097..cf80a2e55bbfbd3e6fd52c7c63b45c9081893e22 100644 (file)
@@ -7341,6 +7341,21 @@ on this reordering ability: On the few platforms where @code{printf()},
 or @file{libintl.so} provides replacement functions, and GNU @code{<libintl.h>}
 activates these replacement functions automatically.
 
+@cindex outdigits
+@cindex Arabic digits
+As a special feature for Farsi (Persian) and maybe Arabic, translators can
+insert an @samp{I} flag into numeric format directives.  For example, the
+translation of @code{"%d"} can be @code{"%Id"}.  The effect of this flag,
+on systems with GNU @code{libc}, is that in the output, the ASCII digits are
+replaced with the @samp{outdigits} defined in the @code{LC_CTYPE} locale
+facet.  On other systems, the @code{gettext} function removes this flag,
+so that it has no effect.
+
+Note that the programmer should @emph{not} put this flag into the
+untranslated string.  (Putting the @samp{I} format directive flag into an
+@var{msgid} string would lead to undefined behaviour on platforms without
+glibc when NLS is disabled.)
+
 @node objc-format, sh-format, c-format, Translators for other Languages
 @subsection Objective C Format Strings
 
index 01cc61bad6856fa0773bde09eb2600110f42e9c2..f3da0cca93c8a52305ecfc283dc6395da9a756d5 100644 (file)
@@ -1,3 +1,43 @@
+2004-01-09  Bruno Haible  <bruno@clisp.org>
+
+       * format.h (struct formatstring_parser): Add 'translated' argument to
+       parse function.
+       (get_sysdep_c_format_directives): Renamed from
+       get_c99_format_directives. Add 'translated' argument. Change meaning
+       of endpos in returned array.
+       * format-c.c (struct spec): Rename field c99_directives to
+       sysdep_directives, and c99_directives_count to sysdep_directives_count.
+       (format_parse): Add 'translated' argument. Handle 'I' flag. Store the
+       pointer past the '>' character instead of the pointer to the '>'.
+       (format_c_parse, format_objc_parse): Add 'translated' argument.
+       (get_sysdep_c_format_directives): Renamed from
+       get_c99_format_directives. Add 'translated' argument.
+       * format-awk.c (format_parse): Add 'translated' argument.
+       * format-csharp.c (format_parse): Likewise.
+       * format-elisp.c (format_parse): Likewise.
+       * format-gcc-internal.c (format_parse): Likewise.
+       * format-java.c (format_parse): Likewise.
+       * format-librep.c (format_parse): Likewise.
+       * format-lisp.c (format_parse): Likewise.
+       * format-pascal.c (format_parse): Likewise.
+       * format-perl-brace.c (format_parse): Likewise.
+       * format-perl.c (format_parse): Likewise.
+       * format-php.c (format_parse): Likewise.
+       * format-python.c (format_parse): Likewise.
+       * format-qt.c (format_parse): Likewise.
+       * format-sh.c (format_parse): Likewise.
+       * format-tcl.c (format_parse): Likewise.
+       * format-ycp.c (format_parse): Likewise.
+       * msgfmt.c (check_pair): Update.
+       * msgmerge.c (msgfmt_check_pair_fails): Likewise.
+       * read-mo.c (get_sysdep_string): Don't add '<'...'>' around segments
+       of length 1.
+       (read_mo_file): Treat major revision 1 like major revision 0.
+       * write-mo.c (write_table): Update. Use major revision 1 if "I" occurs
+       among the sysdep segments.
+       * xgettext.c (set_format_flags_from_context, remember_a_message,
+       remember_a_message_plural): Update.
+
 2004-01-14  Bruno Haible  <bruno@clisp.org>
 
        * msginit.c (fill_header): Avoid a NULL pointer access when the header
index eccc81acc68e54bae214b0e513cef994008af607..27b6654283167efa96a2da983d6da3c269866e1d 100644 (file)
@@ -1,5 +1,5 @@
 /* awk format strings.
-   Copyright (C) 2001-2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2002.
 
    This program is free software; you can redistribute it and/or modify
@@ -96,7 +96,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   unsigned int unnumbered_arg_count;
@@ -634,7 +634,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 86ae6a3ce9971aa292c962e4ec4e4dbcd444adef..8b9b1fce3815603f21d619468ed8dec772b6f09a 100644 (file)
@@ -1,5 +1,5 @@
 /* C format strings.
-   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
@@ -39,7 +39,8 @@
    A directive
    - starts with '%' or '%m$' where m is a positive integer,
    - is optionally followed by any of the characters '#', '0', '-', ' ', '+',
-     "'", each of which acts as a flag,
+     "'", or - only in msgstr strings - the string "I", each of which acts as
+     a flag,
    - is optionally followed by a width specification: '*' (reads an argument)
      or '*m$' or a nonempty digit sequence,
    - is optionally followed by '.' and a precision specification: '*' (reads
@@ -153,8 +154,8 @@ struct spec
   unsigned int unnumbered_arg_count;
   unsigned int allocated;
   struct unnumbered_arg *unnumbered;
-  unsigned int c99_directives_count;
-  const char **c99_directives;
+  unsigned int sysdep_directives_count;
+  const char **sysdep_directives;
 };
 
 /* Locale independent test for a decimal digit.
@@ -177,7 +178,8 @@ numbered_arg_compare (const void *p1, const void *p2)
   xasprintf (_("In the directive number %u, the token after '<' is not the name of a format specifier macro. The valid macro names are listed in ISO C 99 section 7.8.1."), directive_number)
 
 static void *
-format_parse (const char *format, bool objc_extensions, char **invalid_reason)
+format_parse (const char *format, bool translated, bool objc_extensions,
+             char **invalid_reason)
 {
   struct spec spec;
   unsigned int numbered_arg_count;
@@ -190,8 +192,8 @@ format_parse (const char *format, bool objc_extensions, char **invalid_reason)
   spec.allocated = 0;
   numbered = NULL;
   spec.unnumbered = NULL;
-  spec.c99_directives_count = 0;
-  spec.c99_directives = NULL;
+  spec.sysdep_directives_count = 0;
+  spec.sysdep_directives = NULL;
 
   for (; *format != '\0';)
     if (*format++ == '%')
@@ -228,9 +230,26 @@ format_parse (const char *format, bool objc_extensions, char **invalid_reason)
          }
 
        /* Parse flags.  */
-       while (*format == ' ' || *format == '+' || *format == '-'
-              || *format == '#' || *format == '0' || *format == '\'')
-         format++;
+       for (;;)
+         {
+           if (*format == ' ' || *format == '+' || *format == '-'
+               || *format == '#' || *format == '0' || *format == '\'')
+             format++;
+           else if (translated && *format == 'I')
+             {
+               spec.sysdep_directives =
+                 (const char **)
+                 xrealloc (spec.sysdep_directives,
+                           2 * (spec.sysdep_directives_count + 1)
+                           * sizeof (const char *));
+               spec.sysdep_directives[2 * spec.sysdep_directives_count] = format;
+               spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1;
+               spec.sysdep_directives_count++;
+               format++;
+             }
+           else
+             break;
+         }
 
        /* Parse width.  */
        if (*format == '*')
@@ -393,12 +412,12 @@ format_parse (const char *format, bool objc_extensions, char **invalid_reason)
 
        if (*format == '<')
          {
-           spec.c99_directives =
+           spec.sysdep_directives =
              (const char **)
-             xrealloc (spec.c99_directives,
-                       2 * (spec.c99_directives_count + 1)
+             xrealloc (spec.sysdep_directives,
+                       2 * (spec.sysdep_directives_count + 1)
                        * sizeof (const char *));
-           spec.c99_directives[2 * spec.c99_directives_count] = format;
+           spec.sysdep_directives[2 * spec.sysdep_directives_count] = format;
 
            format++;
            /* Parse ISO C 99 section 7.8.1 format string directive.
@@ -547,8 +566,8 @@ format_parse (const char *format, bool objc_extensions, char **invalid_reason)
                goto bad_format;
              }
 
-           spec.c99_directives[2 * spec.c99_directives_count + 1] = format;
-           spec.c99_directives_count++;
+           spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1;
+           spec.sysdep_directives_count++;
          }
        else
          {
@@ -774,21 +793,21 @@ format_parse (const char *format, bool objc_extensions, char **invalid_reason)
     free (numbered);
   if (spec.unnumbered != NULL)
     free (spec.unnumbered);
-  if (spec.c99_directives != NULL)
-    free (spec.c99_directives);
+  if (spec.sysdep_directives != NULL)
+    free (spec.sysdep_directives);
   return NULL;
 }
 
 static void *
-format_c_parse (const char *format, char **invalid_reason)
+format_c_parse (const char *format, bool translated, char **invalid_reason)
 {
-  return format_parse (format, false, invalid_reason);
+  return format_parse (format, translated, false, invalid_reason);
 }
 
 static void *
-format_objc_parse (const char *format, char **invalid_reason)
+format_objc_parse (const char *format, bool translated, char **invalid_reason)
 {
-  return format_parse (format, true, invalid_reason);
+  return format_parse (format, translated, true, invalid_reason);
 }
 
 static void
@@ -798,8 +817,8 @@ format_free (void *descr)
 
   if (spec->unnumbered != NULL)
     free (spec->unnumbered);
-  if (spec->c99_directives != NULL)
-    free (spec->c99_directives);
+  if (spec->sysdep_directives != NULL)
+    free (spec->sysdep_directives);
   free (spec);
 }
 
@@ -873,27 +892,27 @@ struct formatstring_parser formatstring_objc =
 
 
 void
-get_c99_format_directives (const char *string,
-                          struct interval **intervalsp, size_t *lengthp)
+get_sysdep_c_format_directives (const char *string, bool translated,
+                               struct interval **intervalsp, size_t *lengthp)
 {
   /* Parse the format string with all possible extensions turned on.  (The
      caller has already verified that the format string is valid for the
      particular language.)  */
   char *invalid_reason = NULL;
   struct spec *descr =
-    (struct spec *) format_parse (string, true, &invalid_reason);
+    (struct spec *) format_parse (string, translated, true, &invalid_reason);
 
-  if (descr != NULL && descr->c99_directives_count > 0)
+  if (descr != NULL && descr->sysdep_directives_count > 0)
     {
-      unsigned int n = descr->c99_directives_count;
+      unsigned int n = descr->sysdep_directives_count;
       struct interval *intervals =
        (struct interval *) xmalloc (n * sizeof (struct interval));
       unsigned int i;
 
       for (i = 0; i < n; i++)
        {
-         intervals[i].startpos = descr->c99_directives[2 * i] - string;
-         intervals[i].endpos = descr->c99_directives[2 * i + 1] - string;
+         intervals[i].startpos = descr->sysdep_directives[2 * i] - string;
+         intervals[i].endpos = descr->sysdep_directives[2 * i + 1] - string;
        }
       *intervalsp = intervals;
       *lengthp = n;
@@ -1053,7 +1072,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_c_parse (line, &invalid_reason);
+      descr = format_c_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index f7f14f5367607d4fdbe80b48bcab98fd96786c00..f13acc20de735ded055d0dffd12480da20b92266 100644 (file)
@@ -1,5 +1,5 @@
 /* C# format strings.
-   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
@@ -59,7 +59,7 @@ struct spec
 };
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -264,7 +264,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index c050fa6ea3ea8ed2d508ce305e3234b1e5063071..37ae646cc09bbe66c97f0ceed438477d43976503 100644 (file)
@@ -1,5 +1,5 @@
 /* Emacs Lisp format strings.
-   Copyright (C) 2001-2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2002.
 
    This program is free software; you can redistribute it and/or modify
@@ -97,7 +97,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -482,7 +482,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 8a84d2c029fcfce5738edf084b79a67226bf8449..29689916fde496940eade36e8c484a3b19ba9d55 100644 (file)
@@ -1,5 +1,5 @@
 /* GCC internal format strings.
-   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
@@ -112,7 +112,7 @@ struct spec
 
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -401,7 +401,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index c8b9535fc14f1afc7273960b37f1f9e5049c4691..52164c781c14410bda267aaf53b36905b3901c29 100644 (file)
@@ -1,5 +1,5 @@
 /* Java format strings.
-   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
@@ -609,7 +609,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -867,7 +867,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 6380dd62b5a2bc78a7bccdf2de7c80d2df4ffa70..ff7c1caaebb9d567722ffed63e47ec1e4b51f8a6 100644 (file)
@@ -1,5 +1,5 @@
 /* librep format strings.
-   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
@@ -94,7 +94,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -443,7 +443,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index ae25c9a5c55fc940e90602e127949ebc768f1778..4eda24c68fa5a3614fc1a5c128b2d5767a85f2f1 100644 (file)
@@ -1,5 +1,5 @@
 /* Lisp format strings.
-   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
@@ -3265,7 +3265,7 @@ parse_upto (const char **formatp,
 /* ============== Top level format string handling functions ============== */
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -3501,7 +3501,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 0775d3ccba2714e7eddc830fd2b5121f8642f765..e287ed9cbee315df169cfc7f349ea6b6c5e3a27b 100644 (file)
@@ -1,5 +1,5 @@
 /* Object Pascal format strings.
-   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
@@ -105,7 +105,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   unsigned int directives;
   unsigned int numbered_arg_count;
@@ -535,7 +535,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 26149d8de5409abc93f4627b0953c573c77afcc1..5da2c14dbbf96e6cdce778d8a69b97f8d207f042 100644 (file)
@@ -1,5 +1,5 @@
 /* Perl brace format strings.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -62,7 +62,7 @@ named_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -271,7 +271,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 3111727d58794e194120b578ba825d93722357d7..9131adfe9039a4f3e40b7e6ac35034f7db11bf89 100644 (file)
@@ -1,5 +1,5 @@
 /* Perl format strings.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -131,7 +131,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   unsigned int directives;
   unsigned int numbered_arg_count;
@@ -742,7 +742,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index d76698484257e9428e51018e8329de941c3c4f26..87d6d34d0d901c6bfa56016ccfca687fe97d8d61 100644 (file)
@@ -1,5 +1,5 @@
 /* PHP format strings.
-   Copyright (C) 2001-2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2002.
 
    This program is free software; you can redistribute it and/or modify
@@ -96,7 +96,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   unsigned int directives;
   unsigned int numbered_arg_count;
@@ -479,7 +479,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index d41adfe902b43ae14d2be1d22fc542043ef89457..418b9d404cbcc2fdc47ea0cdec9476571f98d379 100644 (file)
@@ -1,5 +1,5 @@
 /* Python format strings.
-   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
@@ -115,7 +115,7 @@ named_arg_compare (const void *p1, const void *p2)
   xstrdup (_("The string refers to arguments both through argument names and through unnamed argument specifications."))
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -653,7 +653,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 715d10be580e5a844959e04c12dc60f2320bfb95..6cd174f8c5747ede13b4716d1d2524e0519c519f 100644 (file)
@@ -1,5 +1,5 @@
 /* Qt format strings.
-   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
@@ -53,7 +53,7 @@ struct spec
 
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -206,7 +206,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 798d3d0fad0817405956c162f07db91e943282a3..38c25e28694697a3b69e8e9fdd11cb58f24166f5 100644 (file)
@@ -1,5 +1,5 @@
 /* Shell format strings.
-   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
@@ -88,7 +88,7 @@ named_arg_compare (const void *p1, const void *p2)
   xstrdup (_("The string refers to a shell variable with an empty name."))
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -377,7 +377,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 0b3e871cff8b1bf24b0099a29bf7eee054c65682..4f8d7c1fb2aa9b8ad85f30872abfa4632aa36f13 100644 (file)
@@ -1,5 +1,5 @@
 /* Tcl format strings.
-   Copyright (C) 2001-2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2002.
 
    This program is free software; you can redistribute it and/or modify
@@ -100,7 +100,7 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -527,7 +527,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 6300e97bb3a848c08664539d2615a1f32ac1f167..c3799eb05db7fba3cab7fe377af80a8ec61fc48e 100644 (file)
@@ -1,5 +1,5 @@
 /* YCP and Smalltalk format strings.
-   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
@@ -50,7 +50,7 @@ struct spec
 
 
 static void *
-format_parse (const char *format, char **invalid_reason)
+format_parse (const char *format, bool translated, char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -216,7 +216,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, &invalid_reason);
+      descr = format_parse (line, false, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 406c0853bc68b85f2e06fc705405c6d8ac280951..b28c0a5bf00f344314c279dab558784859f7c495 100644 (file)
@@ -1,5 +1,5 @@
 /* Format strings.
-   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
@@ -34,12 +34,14 @@ extern "C" {
 struct formatstring_parser
 {
   /* Parse the given string as a format string.
+     If translated is true, some extensions available only to msgstr but not
+     to msgid strings are recognized.
      Return a freshly allocated structure describing
        1. the argument types/names needed for the format string,
        2. the total number of format directives.
      Return NULL if the string is not a valid format string. In this case,
      also set *invalid_reason to an error message explaining why.  */
-  void * (*parse) (const char *string, char **invalid_reason);
+  void * (*parse) (const char *string, bool translated, char **invalid_reason);
 
   /* Free a format string descriptor, returned by parse().  */
   void (*free) (void *descr);
@@ -84,16 +86,19 @@ extern DLL_VARIABLE struct formatstring_parser formatstring_qt;
 /* Table of all format string parsers.  */
 extern DLL_VARIABLE struct formatstring_parser *formatstring_parsers[NFORMATS];
 
-/* Returns an array of the ISO C 99 <inttypes.h> format directives
-   contained in the argument string.  *intervalsp is assigned to a freshly
-   allocated array of intervals (startpos pointing to '<', endpos to '>'),
+/* Returns an array of the ISO C 99 <inttypes.h> format directives and other
+   format flags or directives with a system dependent expansion contained in
+   the argument string.  *intervalsp is assigned to a freshly allocated array
+   of intervals (startpos pointing to '<', endpos to the character after '>'),
    and *lengthp is assigned to the number of intervals in this array.  */
 struct interval
 {
   size_t startpos;
   size_t endpos;
 };
-extern void get_c99_format_directives (const char *string, struct interval **intervalsp, size_t *lengthp);
+extern void
+       get_sysdep_c_format_directives (const char *string, bool translated,
+                                struct interval **intervalsp, size_t *lengthp);
 
 
 #ifdef __cplusplus
index 5c48e506b76a755e53101c338ba588a8b5d37f30..209953b0bf27a599ba92090688fd507d0ac85677 100644 (file)
@@ -1274,7 +1274,7 @@ check_pair (const char *msgid,
          char *invalid_reason = NULL;
          void *msgid_descr =
            parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
-                          &invalid_reason);
+                          false, &invalid_reason);
 
          if (msgid_descr != NULL)
            {
@@ -1293,7 +1293,7 @@ check_pair (const char *msgid,
                      pretty_msgstr = buf;
                    }
 
-                 msgstr_descr = parser->parse (p, &invalid_reason);
+                 msgstr_descr = parser->parse (p, true, &invalid_reason);
 
                  if (msgstr_descr != NULL)
                    {
index 34c44fe1206581fe40c969eb5b22ecfda2d9fb49..3a4478ef723b61dcad6a7c193877733cc7e12179 100644 (file)
@@ -576,7 +576,7 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos,
   struct formatstring_parser *parser = formatstring_parsers[fmt];
   char *invalid_reason = NULL;
   void *msgid_descr =
-    parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
+    parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false,
                   &invalid_reason);
 
   failure = false;
@@ -587,7 +587,7 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos,
 
       for (p = msgstr; p < p_end; p += strlen (p) + 1)
        {
-         void *msgstr_descr = parser->parse (msgstr, &invalid_reason);
+         void *msgstr_descr = parser->parse (msgstr, true, &invalid_reason);
 
          if (msgstr_descr != NULL)
            {
index 8328347b73c1522e6f60d706f9df27b6e284716f..a5d69f6c8fa219c4bd732186ecf86d5c2e1ddfc8 100644 (file)
@@ -1,5 +1,5 @@
 /* Reading binary .mo files.
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
    Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
 
    This program is free software; you can redistribute it and/or modify
@@ -147,6 +147,7 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
       nls_uint32 sysdep_segment_offset;
       nls_uint32 ss_length;
       nls_uint32 ss_offset;
+      size_t n;
 
       length += segsize;
 
@@ -170,7 +171,8 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
                 _("file \"%s\" contains a not NUL terminated string, at %s"),
                 bfp->filename, location);
        }
-      length += 1 + strlen (bfp->data + ss_offset) + 1;
+      n = strlen (bfp->data + ss_offset);
+      length += (n > 1 ? 1 + n + 1 : n);
     }
 
   /* Allocate and fill the string.  */
@@ -205,10 +207,12 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
       if (!(ss_length > 0 && bfp->data[ss_offset + ss_length - 1] == '\0'))
        abort ();
       n = strlen (bfp->data + ss_offset);
-      *p++ = '<';
+      if (n > 1)
+       *p++ = '<';
       memcpy (p, bfp->data + ss_offset, n);
       p += n;
-      *p++ = '>';
+      if (n > 1)
+       *p++ = '>';
     }
 
   if (p != string + length)
@@ -267,11 +271,12 @@ read_mo_file (message_list_ty *mlp, const char *filename)
 
   header.revision = GET_HEADER_FIELD (revision);
 
-  /* We support only the major revision 0.  */
+  /* We support only the major revisions 0 and 1.  */
   switch (header.revision >> 16)
     {
     case 0:
-      /* Fill the header parts that apply to major revision 0.  */
+    case 1:
+      /* Fill the header parts that apply to major revisions 0 and 1.  */
       header.nstrings = GET_HEADER_FIELD (nstrings);
       header.orig_tab_offset = GET_HEADER_FIELD (orig_tab_offset);
       header.trans_tab_offset = GET_HEADER_FIELD (trans_tab_offset);
index 7402c282721c2d52d11ba9f299cd51dcb350775e..2bdb52afad9037a5c4fa35e91db2134ecd715eb8 100644 (file)
@@ -1,5 +1,5 @@
 /* Writing binary .mo files.
-   Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2004 Free Software Foundation, Inc.
    Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
 
    This program is free software; you can redistribute it and/or modify
@@ -143,6 +143,8 @@ write_table (FILE *output_file, message_list_ty *mlp)
   struct pre_sysdep_message *sysdep_msg_arr;
   size_t n_sysdep_segments;
   struct pre_sysdep_segment *sysdep_segments;
+  bool have_outdigits;
+  int major_revision;
   int minor_revision;
   bool omit_hash_table;
   nls_uint32 hash_tab_size;
@@ -169,6 +171,7 @@ write_table (FILE *output_file, message_list_ty *mlp)
     xmalloc (mlp->nitems * sizeof (struct pre_sysdep_message));
   n_sysdep_segments = 0;
   sysdep_segments = NULL;
+  have_outdigits = false;
   for (j = 0; j < mlp->nitems; j++)
     {
       message_ty *mp = mlp->item[j];
@@ -191,8 +194,8 @@ write_table (FILE *output_file, message_list_ty *mlp)
          const char *p_end;
          const char *p;
 
-         get_c99_format_directives (mp->msgid,
-                                    &intervals[M_ID], &nintervals[M_ID]);
+         get_sysdep_c_format_directives (mp->msgid, false,
+                                         &intervals[M_ID], &nintervals[M_ID]);
 
          p_end = mp->msgstr + mp->msgstr_len;
          for (p = mp->msgstr; p < p_end; p += strlen (p) + 1)
@@ -200,7 +203,9 @@ write_table (FILE *output_file, message_list_ty *mlp)
              struct interval *part_intervals;
              size_t part_nintervals;
 
-             get_c99_format_directives (p, &part_intervals, &part_nintervals);
+             get_sysdep_c_format_directives (p, true,
+                                             &part_intervals,
+                                             &part_nintervals);
              if (part_nintervals > 0)
                {
                  size_t d = p - mp->msgstr;
@@ -259,10 +264,15 @@ write_table (FILE *output_file, message_list_ty *mlp)
                  pre->segments[i].segptr = str + lastpos;
                  pre->segments[i].segsize = intervals[m][i].startpos - lastpos;
 
-                 /* The "+ 1" skips the '<' marker.  */
-                 length =
-                   intervals[m][i].endpos - (intervals[m][i].startpos + 1);
-                 pointer = str + (intervals[m][i].startpos + 1);
+                 length = intervals[m][i].endpos - intervals[m][i].startpos;
+                 pointer = str + intervals[m][i].startpos;
+                 if (length >= 2
+                     && pointer[0] == '<' && pointer[length - 1] == '>')
+                   {
+                     /* Skip the '<' and '>' markers.  */
+                     length -= 2;
+                     pointer += 1;
+                   }
 
                  for (r = 0; r < n_sysdep_segments; r++)
                    if (sysdep_segments[r].length == length
@@ -283,8 +293,10 @@ write_table (FILE *output_file, message_list_ty *mlp)
 
                  pre->segments[i].sysdepref = r;
 
-                 /* The "+ 1" skips the '>' marker.  */
-                 lastpos = intervals[m][i].endpos + 1;
+                 if (length == 1 && *pointer == 'I')
+                   have_outdigits = true;
+
+                 lastpos = intervals[m][i].endpos;
                }
              pre->segments[i].segptr = str + lastpos;
              pre->segments[i].segsize = str_len - lastpos;
@@ -320,6 +332,12 @@ write_table (FILE *output_file, message_list_ty *mlp)
   if (nstrings > 0)
     qsort (msg_arr, nstrings, sizeof (struct pre_message), compare_id);
 
+  /* We need major revision 1 if there are system dependent strings that use
+     "I" because older versions of gettext() crash when this occurs in a .mo
+     file.  Otherwise use major revision 0.  */
+  major_revision =
+    (have_outdigits ? MO_REVISION_NUMBER_WITH_SYSDEP_I : MO_REVISION_NUMBER);
+
   /* We need minor revision 1 if there are system dependent strings.
      Otherwise we choose minor revision 0 because it's supported by older
      versions of libintl and revision 1 isn't.  */
@@ -365,7 +383,7 @@ write_table (FILE *output_file, message_list_ty *mlp)
   /* Magic number.  */
   header.magic = _MAGIC;
   /* Revision number of file format.  */
-  header.revision = (MO_REVISION_NUMBER << 16) + minor_revision;
+  header.revision = (major_revision << 16) + minor_revision;
 
   header_size =
     (minor_revision == 0
index 979a2034e0c7ad6d01e68230c0fe11116a3eec48..7a4ab62391fc7ccafc107317e5f6f7d8960f39d9 100644 (file)
@@ -1700,7 +1700,7 @@ set_format_flags_from_context (enum is_format is_format[NFORMATS],
          {
            struct formatstring_parser *parser = formatstring_parsers[i];
            char *invalid_reason = NULL;
-           void *descr = parser->parse (string, &invalid_reason);
+           void *descr = parser->parse (string, false, &invalid_reason);
 
            if (descr != NULL)
              parser->free (descr);
@@ -1921,7 +1921,7 @@ meta information, not the empty string.\n")));
        {
          struct formatstring_parser *parser = formatstring_parsers[i];
          char *invalid_reason = NULL;
-         void *descr = parser->parse (mp->msgid, &invalid_reason);
+         void *descr = parser->parse (mp->msgid, false, &invalid_reason);
 
          if (descr != NULL)
            {
@@ -2021,7 +2021,8 @@ remember_a_message_plural (message_ty *mp, char *string,
          {
            struct formatstring_parser *parser = formatstring_parsers[i];
            char *invalid_reason = NULL;
-           void *descr = parser->parse (mp->msgid_plural, &invalid_reason);
+           void *descr =
+             parser->parse (mp->msgid_plural, false, &invalid_reason);
 
            if (descr != NULL)
              {
index 8eb84522671d57ea149146b7314892eda58e851b..705301d8a21e7208cb0f7edc6edd9b63f9d6a313 100644 (file)
@@ -1,3 +1,11 @@
+2004-01-11  Bruno Haible  <bruno@clisp.org>
+
+       * format-c-5: New file.
+       * format-c-5-prg.c: New file.
+       * Makefile.am (TESTS): Add format-c-5.
+       (noinst_PROGRAMS): Add fc5.
+       (fc5_SOURCES, fc5_LDADD): New variables.
+
 2004-01-09  Bruno Haible  <bruno@clisp.org>
 
        * tstgettext.c (main): Update year in --version output.
index 8015ace4216620094113868bb21f4e62e0e5cbcb..c02b8682cfde36e186112a772f9cdb39e4f9430a 100644 (file)
@@ -82,7 +82,7 @@ TESTS = gettext-1 gettext-2 \
        xgettext-tcl-1 xgettext-tcl-2 \
        xgettext-ycp-1 xgettext-ycp-2 \
        format-awk-1 format-awk-2 \
-       format-c-1 format-c-2 format-c-3 format-c-4 \
+       format-c-1 format-c-2 format-c-3 format-c-4 format-c-5 \
        format-csharp-1 format-csharp-2 \
        format-elisp-1 format-elisp-2 \
        format-gcc-internal-1 format-gcc-internal-2 \
@@ -161,7 +161,7 @@ DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
 LDADD = $(LDADD_@USE_INCLUDED_LIBINTL@)
 LDADD_yes = ../intl/libintl.la
 LDADD_no = ../intl/libgnuintl.la @LTLIBINTL@
-noinst_PROGRAMS = tstgettext tstngettext testlocale cake fc3 fc4
+noinst_PROGRAMS = tstgettext tstngettext testlocale cake fc3 fc4 fc5
 tstgettext_SOURCES = tstgettext.c setlocale.c
 tstgettext_CFLAGS = -DINSTALLDIR=\".\"
 tstgettext_LDADD = ../lib/libgettextlib.la $(LDADD)
@@ -175,6 +175,8 @@ fc3_SOURCES = format-c-3-prg.c setlocale.c
 fc3_LDADD = ../lib/libgettextlib.la $(LDADD)
 fc4_SOURCES = format-c-4-prg.c setlocale.c
 fc4_LDADD = ../lib/libgettextlib.la $(LDADD)
+fc5_SOURCES = format-c-5-prg.c
+fc5_LDADD = ../lib/libgettextlib.la $(LDADD)
 
 # Clean up after Solaris cc.
 clean-local: