as 'c-format'.
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#.
+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
/* 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
/* 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
/* 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;
}
}
}
+ /* 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;
}
/* 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));
+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.
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
+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
/* 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
}
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;
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");
/* 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
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
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.
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;
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++ == '%')
}
/* 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 == '*')
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.
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
{
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
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);
}
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;
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");
/* 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
};
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;
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");
/* 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
}
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;
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");
/* 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
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;
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");
/* 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
}
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;
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");
/* 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
}
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;
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");
/* 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
/* ============== 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;
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");
/* 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
}
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;
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");
/* 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
}
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;
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");
/* 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
}
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;
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");
/* 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
}
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;
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");
/* 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
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;
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");
/* 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
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;
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");
/* 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
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;
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");
/* 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
}
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;
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");
/* 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
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;
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");
/* 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
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);
/* 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
char *invalid_reason = NULL;
void *msgid_descr =
parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
- &invalid_reason);
+ false, &invalid_reason);
if (msgid_descr != NULL)
{
pretty_msgstr = buf;
}
- msgstr_descr = parser->parse (p, &invalid_reason);
+ msgstr_descr = parser->parse (p, true, &invalid_reason);
if (msgstr_descr != NULL)
{
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;
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)
{
/* 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
nls_uint32 sysdep_segment_offset;
nls_uint32 ss_length;
nls_uint32 ss_offset;
+ size_t n;
length += segsize;
_("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. */
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)
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);
/* 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
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;
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];
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)
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;
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
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;
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. */
/* 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
{
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);
{
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)
{
{
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)
{
+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.
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 \
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)
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: