From: Bruno Haible Date: Thu, 15 Jan 2004 11:36:37 +0000 (+0000) Subject: Support for the 'I' flag that translators can use in messages marked X-Git-Tag: v0.14~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6bd2dedd09a7e568d2cab744428459b46681f3f9;p=thirdparty%2Fgettext.git Support for the 'I' flag that translators can use in messages marked as 'c-format'. --- diff --git a/NEWS b/NEWS index 48496b2dd..16f919820 100644 --- 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#. diff --git a/gettext-runtime/intl/ChangeLog b/gettext-runtime/intl/ChangeLog index ef1f0d945..56c1449a8 100644 --- a/gettext-runtime/intl/ChangeLog +++ b/gettext-runtime/intl/ChangeLog @@ -1,3 +1,9 @@ +2004-01-09 Bruno Haible + + * 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 * loadmsgcat.c (_nl_load_domain): When a string pair uses a system diff --git a/gettext-runtime/intl/gmo.h b/gettext-runtime/intl/gmo.h index d1fe4d6b8..e7c9cc14b 100644 --- a/gettext-runtime/intl/gmo.h +++ b/gettext-runtime/intl/gmo.h @@ -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; diff --git a/gettext-runtime/intl/loadmsgcat.c b/gettext-runtime/intl/loadmsgcat.c index 5d658538a..99c51b4c5 100644 --- a/gettext-runtime/intl/loadmsgcat.c +++ b/gettext-runtime/intl/loadmsgcat.c @@ -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)); diff --git a/gettext-tools/doc/ChangeLog b/gettext-tools/doc/ChangeLog index fc983d5e2..e6ef3e5fe 100644 --- a/gettext-tools/doc/ChangeLog +++ b/gettext-tools/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-01-09 Bruno Haible + + * gettext.texi (c-format): Document the 'I' flag. + 2004-01-14 Bruno Haible * gettext.texi: Add entrypoints for ngettext and envsubst. diff --git a/gettext-tools/doc/gettext.texi b/gettext-tools/doc/gettext.texi index 785540884..cf80a2e55 100644 --- a/gettext-tools/doc/gettext.texi +++ b/gettext-tools/doc/gettext.texi @@ -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{} 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 diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 01cc61bad..f3da0cca9 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,43 @@ +2004-01-09 Bruno Haible + + * 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 * msginit.c (fill_header): Avoid a NULL pointer access when the header diff --git a/gettext-tools/src/format-awk.c b/gettext-tools/src/format-awk.c index eccc81acc..27b665428 100644 --- a/gettext-tools/src/format-awk.c +++ b/gettext-tools/src/format-awk.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-c.c b/gettext-tools/src/format-c.c index 86ae6a3ce..8b9b1fce3 100644 --- a/gettext-tools/src/format-c.c +++ b/gettext-tools/src/format-c.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-csharp.c b/gettext-tools/src/format-csharp.c index f7f14f536..f13acc20d 100644 --- a/gettext-tools/src/format-csharp.c +++ b/gettext-tools/src/format-csharp.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-elisp.c b/gettext-tools/src/format-elisp.c index c050fa6ea..37ae646cc 100644 --- a/gettext-tools/src/format-elisp.c +++ b/gettext-tools/src/format-elisp.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-gcc-internal.c b/gettext-tools/src/format-gcc-internal.c index 8a84d2c02..29689916f 100644 --- a/gettext-tools/src/format-gcc-internal.c +++ b/gettext-tools/src/format-gcc-internal.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-java.c b/gettext-tools/src/format-java.c index c8b9535fc..52164c781 100644 --- a/gettext-tools/src/format-java.c +++ b/gettext-tools/src/format-java.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-librep.c b/gettext-tools/src/format-librep.c index 6380dd62b..ff7c1caae 100644 --- a/gettext-tools/src/format-librep.c +++ b/gettext-tools/src/format-librep.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-lisp.c b/gettext-tools/src/format-lisp.c index ae25c9a5c..4eda24c68 100644 --- a/gettext-tools/src/format-lisp.c +++ b/gettext-tools/src/format-lisp.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-pascal.c b/gettext-tools/src/format-pascal.c index 0775d3ccb..e287ed9cb 100644 --- a/gettext-tools/src/format-pascal.c +++ b/gettext-tools/src/format-pascal.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-perl-brace.c b/gettext-tools/src/format-perl-brace.c index 26149d8de..5da2c14db 100644 --- a/gettext-tools/src/format-perl-brace.c +++ b/gettext-tools/src/format-perl-brace.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-perl.c b/gettext-tools/src/format-perl.c index 3111727d5..9131adfe9 100644 --- a/gettext-tools/src/format-perl.c +++ b/gettext-tools/src/format-perl.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-php.c b/gettext-tools/src/format-php.c index d76698484..87d6d34d0 100644 --- a/gettext-tools/src/format-php.c +++ b/gettext-tools/src/format-php.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-python.c b/gettext-tools/src/format-python.c index d41adfe90..418b9d404 100644 --- a/gettext-tools/src/format-python.c +++ b/gettext-tools/src/format-python.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-qt.c b/gettext-tools/src/format-qt.c index 715d10be5..6cd174f8c 100644 --- a/gettext-tools/src/format-qt.c +++ b/gettext-tools/src/format-qt.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-sh.c b/gettext-tools/src/format-sh.c index 798d3d0fa..38c25e286 100644 --- a/gettext-tools/src/format-sh.c +++ b/gettext-tools/src/format-sh.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-tcl.c b/gettext-tools/src/format-tcl.c index 0b3e871cf..4f8d7c1fb 100644 --- a/gettext-tools/src/format-tcl.c +++ b/gettext-tools/src/format-tcl.c @@ -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 , 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"); diff --git a/gettext-tools/src/format-ycp.c b/gettext-tools/src/format-ycp.c index 6300e97bb..c3799eb05 100644 --- a/gettext-tools/src/format-ycp.c +++ b/gettext-tools/src/format-ycp.c @@ -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 , 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"); diff --git a/gettext-tools/src/format.h b/gettext-tools/src/format.h index 406c0853b..b28c0a5bf 100644 --- a/gettext-tools/src/format.h +++ b/gettext-tools/src/format.h @@ -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 , 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 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 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 diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c index 5c48e506b..209953b0b 100644 --- a/gettext-tools/src/msgfmt.c +++ b/gettext-tools/src/msgfmt.c @@ -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) { diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c index 34c44fe12..3a4478ef7 100644 --- a/gettext-tools/src/msgmerge.c +++ b/gettext-tools/src/msgmerge.c @@ -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) { diff --git a/gettext-tools/src/read-mo.c b/gettext-tools/src/read-mo.c index 8328347b7..a5d69f6c8 100644 --- a/gettext-tools/src/read-mo.c +++ b/gettext-tools/src/read-mo.c @@ -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 , 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); diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c index 7402c2827..2bdb52afa 100644 --- a/gettext-tools/src/write-mo.c +++ b/gettext-tools/src/write-mo.c @@ -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 , 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 diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index 979a2034e..7a4ab6239 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -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) { diff --git a/gettext-tools/tests/ChangeLog b/gettext-tools/tests/ChangeLog index 8eb845226..705301d8a 100644 --- a/gettext-tools/tests/ChangeLog +++ b/gettext-tools/tests/ChangeLog @@ -1,3 +1,11 @@ +2004-01-11 Bruno Haible + + * 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 * tstgettext.c (main): Update year in --version output. diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 8015ace42..c02b8682c 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -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: