* gettext-tools/src/pos.h: Include <stdbool.h>.
(pos_filename_has_spaces): New declaration.
* gettext-tools/src/pos.c: New file.
* gettext-tools/src/msgl-ofn.h: New file.
* gettext-tools/src/msgl-ofn.c: New file.
* gettext-tools/src/FILES: Update.
* gettext-tools/src/Makefile.am (noinst_HEADERS): Add msgl-ofn.h.
(COMMON_SOURCE): Add pos.c.
(libgettextsrc_la_SOURCES): Add msgl-ofn.c.
* gettext-tools/libgettextpo/Makefile.am (libgettextpo_la_AUXSOURCES): Likewise.
* gettext-tools/src/write-catalog.h (struct catalog_output_format): Add field
requires_utf8_for_filenames_with_spaces.
* gettext-tools/src/xgettext.c: Include pos.h, msgl-ofn.h.
(finalize_header): Convert the message domain to UTF-8 also when some message
has file names with spaces.
* gettext-tools/src/write-po.h (message_print_comment_filepos): Add charset
parameter.
* gettext-tools/src/write-po.c: Include pos.h.
(message_print_comment_filepos): Add charset parameter. If a file name has
spaces, enclose it in U+2068 and U+2069 characters.
(message_print, message_print_obsolete, output_format_po): Update.
* gettext-tools/src/write-properties.c (write_message,
output_format_properties): Update.
* gettext-tools/src/write-stringtable.c (output_format_stringtable): Update.
* gettext-tools/tests/xgettext-17: New file.
* gettext-tools/tests/Makefile.am (TESTS): Add it.
## Makefile for the gettext-tools/libgettextpo subdirectory of GNU gettext
-## Copyright (C) 1995-1998, 2000-2016, 2019-2020 Free Software Foundation, Inc.
+## Copyright (C) 1995-1998, 2000-2016, 2019-2021 Free Software Foundation, Inc.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
../src/str-list.c \
../src/dir-list.c \
../src/message.c \
+ ../src/pos.c \
../src/msgl-ascii.c \
../src/po-error.c \
../src/po-xerror.c \
Language names according to ISO 639.
pos.h
+pos.c
Source file positions.
message.h
msgl-ascii.c
Message list test for ASCII character set.
+msgl-ofn.h
+msgl-ofn.c
+ Message list test for ordinary file names.
+
po-error.h
po-error.c
po-xerror.h
## Makefile for the gettext-tools/src subdirectory of GNU gettext
-## Copyright (C) 1995-1998, 2000-2020 Free Software Foundation, Inc.
+## Copyright (C) 1995-1998, 2000-2021 Free Software Foundation, Inc.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
write-catalog.h write-po.h write-properties.h write-stringtable.h \
dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h cldr-plural.h \
cldr-plural-exp.h locating-rule.h its.h search-path.h \
- msgl-charset.h msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-header.h \
- msgl-english.h msgl-check.h msgl-fsearch.h msgfmt.h msgunfmt.h \
+ msgl-charset.h msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-ofn.h msgl-cat.h \
+ msgl-header.h msgl-english.h msgl-check.h msgl-fsearch.h msgfmt.h msgunfmt.h \
plural-count.h plural-eval.h plural-distrib.h \
read-mo.h write-mo.h \
read-java.h write-java.h \
# (read-catalog-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> open-catalog.c -> dir-list.c -> str-list.c.
# (read-catalog-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> po-charset.c.
# (read-catalog-abstract.c <--> po-gram-gen.y <--> po-lex.c) -> message.c -> str-list.c.
-COMMON_SOURCE = message.c po-error.c po-xerror.c \
+COMMON_SOURCE = message.c pos.c po-error.c po-xerror.c \
read-catalog-abstract.c po-lex.c po-gram-gen.y po-charset.c \
read-po.c read-properties.c read-stringtable.c open-catalog.c \
dir-list.c str-list.c
# libgettextsrc contains all code that is needed by at least two programs.
libgettextsrc_la_SOURCES = \
-$(COMMON_SOURCE) read-catalog.c \
-write-catalog.c write-properties.c write-stringtable.c write-po.c \
-msgl-ascii.c msgl-iconv.c msgl-equal.c msgl-cat.c msgl-header.c msgl-english.c \
-msgl-check.c file-list.c msgl-charset.c po-time.c plural-exp.c plural-eval.c \
-plural-table.c quote.h sentence.h sentence.c \
-$(FORMAT_SOURCE) \
-read-desktop.c locating-rule.c its.c search-path.c
+ $(COMMON_SOURCE) \
+ read-catalog.c \
+ write-catalog.c write-properties.c write-stringtable.c write-po.c \
+ msgl-ascii.c \
+ msgl-ofn.c \
+ msgl-iconv.c \
+ msgl-equal.c \
+ msgl-cat.c \
+ msgl-header.c \
+ msgl-english.c \
+ msgl-check.c \
+ file-list.c \
+ msgl-charset.c \
+ po-time.c \
+ plural-exp.c plural-eval.c plural-table.c \
+ quote.h \
+ sentence.h sentence.c \
+ $(FORMAT_SOURCE) \
+ read-desktop.c \
+ locating-rule.c its.c \
+ search-path.c
# msggrep needs pattern matching.
LIBGREP = ../libgrep/libgrep.a
--- /dev/null
+/* Message list test for ordinary file names.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* Specification. */
+#include "msgl-ofn.h"
+
+#include "pos.h"
+
+
+bool
+message_has_filenames_with_spaces (message_ty *mp)
+{
+ size_t n = mp->filepos_count;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ if (pos_filename_has_spaces (&mp->filepos[i]))
+ return true;
+
+ return false;
+}
+
+bool
+message_list_has_filenames_with_spaces (message_list_ty *mlp)
+{
+ size_t j;
+
+ for (j = 0; j < mlp->nitems; j++)
+ if (message_has_filenames_with_spaces (mlp->item[j]))
+ return true;
+
+ return false;
+}
+
+bool
+msgdomain_list_has_filenames_with_spaces (msgdomain_list_ty *mdlp)
+{
+ size_t k;
+
+ for (k = 0; k < mdlp->nitems; k++)
+ if (message_list_has_filenames_with_spaces (mdlp->item[k]->messages))
+ return true;
+
+ return false;
+}
--- /dev/null
+/* Message list test for ordinary file names.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#ifndef _MSGL_OFN_H
+#define _MSGL_OFN_H
+
+#include "message.h"
+
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Tests whether some of the file names in the message locations has spaces. */
+
+extern bool
+ message_has_filenames_with_spaces (message_ty *mp);
+extern bool
+ message_list_has_filenames_with_spaces (message_list_ty *mlp);
+extern bool
+ msgdomain_list_has_filenames_with_spaces (msgdomain_list_ty *mdlp);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MSGL_OFN_H */
--- /dev/null
+/* Source file positions.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "pos.h"
+
+#include <string.h>
+
+bool
+pos_filename_has_spaces (const struct lex_pos_ty *pos)
+{
+ const char *filename = pos->file_name;
+
+ return strchr (filename, ' ') != NULL || strchr (filename, '\t') != NULL;
+}
/* Source file positions.
- Copyright (C) 1995-1998, 2000-2001 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2001, 2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Get size_t. */
#include <stddef.h>
+/* Get bool. */
+#include <stdbool.h>
+
/* Position of a message within a source file.
Used for error reporting purposes. */
typedef struct lex_pos_ty lex_pos_ty;
size_t line_number;
};
+/* Determines whether the file name in the position has spaces.
+ Such spaces need special protection in PO files and .properties files. */
+extern bool pos_filename_has_spaces (const struct lex_pos_ty *pos);
+
#endif /* _POS_H */
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2019 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2019, 2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
encoding. */
bool requires_utf8;
+ /* Whether the print function uses Unicode control characters to protect
+ against filenames with spaces. */
+ bool requires_utf8_for_filenames_with_spaces;
+
/* Whether the print function supports styled output. */
bool supports_color;
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2010, 2012, 2014-2015, 2018-2020 Free Software
+ Copyright (C) 1995-1998, 2000-2010, 2012, 2014-2015, 2018-2021 Free Software
Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
#include "format.h"
#include "unilbrk.h"
#include "msgl-ascii.h"
+#include "pos.h"
#include "write-catalog.h"
#include "xalloc.h"
#include "xmalloca.h"
void
message_print_comment_filepos (const message_ty *mp, ostream_t stream,
- bool uniforum, size_t page_width)
+ const char *charset, bool uniforum,
+ size_t page_width)
{
if (filepos_comment_type != filepos_comment_none
&& mp->filepos_count != 0)
}
else
{
+ const char *canon_charset;
size_t column;
size_t j;
+ canon_charset = po_charset_canonicalize (charset);
+
ostream_write_str (stream, "#:");
column = 2;
for (j = 0; j < filepos_count; ++j)
lex_pos_ty *pp;
char buffer[21];
const char *cp;
- size_t len;
+ size_t width;
pp = &filepos[j];
cp = pp->file_name;
buffer[0] = '\0';
else
sprintf (buffer, ":%ld", (long) pp->line_number);
- len = strlen (cp) + strlen (buffer) + 1;
- if (column > 2 && column + len > page_width)
+ /* File names are usually entirely ASCII. Therefore strlen is
+ sufficient to determine their printed width. */
+ width = strlen (cp) + strlen (buffer) + 1;
+ if (column > 2 && column + width > page_width)
{
ostream_write_str (stream, "\n#:");
column = 2;
}
ostream_write_str (stream, " ");
begin_css_class (stream, class_reference);
- ostream_write_str (stream, cp);
+ if (pos_filename_has_spaces (pp))
+ {
+ /* Enclose the file name within U+2068 and U+2069 characters,
+ so that it can be parsed unambiguously. */
+ if (canon_charset == po_charset_utf8)
+ {
+ ostream_write_str (stream, "\xE2\x81\xA8"); /* U+2068 */
+ ostream_write_str (stream, cp);
+ ostream_write_str (stream, "\xE2\x81\xA9"); /* U+2069 */
+ }
+ else if (canon_charset != NULL
+ && strcmp (canon_charset, "GB18030") == 0)
+ {
+ ostream_write_str (stream, "\x81\x36\xAC\x34"); /* U+2068 */
+ ostream_write_str (stream, cp);
+ ostream_write_str (stream, "\x81\x36\xAC\x35"); /* U+2069 */
+ }
+ else
+ abort ();
+ }
+ else
+ ostream_write_str (stream, cp);
ostream_write_str (stream, buffer);
end_css_class (stream, class_reference);
- column += len;
+ column += width;
}
ostream_write_str (stream, "\n");
}
/* Print the file position comments. This will help a human who is
trying to navigate the sources. There is no problem of getting
repeated positions, because duplicates are checked for. */
- message_print_comment_filepos (mp, stream, uniforum, page_width);
+ message_print_comment_filepos (mp, stream, charset, uniforum, page_width);
/* Print flag information in special comment. */
message_print_comment_flags (mp, stream, debug);
message_print_comment_dot (mp, stream);
/* Print the file position comments (normally empty). */
- message_print_comment_filepos (mp, stream, uniforum, page_width);
+ message_print_comment_filepos (mp, stream, charset, uniforum, page_width);
/* Print flag information in special comment.
Preserve only
{
msgdomain_list_print_po, /* print */
false, /* requires_utf8 */
+ true, /* requires_utf8_for_filenames_with_spaces */
true, /* supports_color */
true, /* supports_multiple_domains */
true, /* supports_contexts */
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2014, 2018-2019 Free Software
+ Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2014, 2018-2019, 2021 Free Software
Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
message_print_comment_dot (const message_ty *mp, ostream_t stream);
extern void
message_print_comment_filepos (const message_ty *mp, ostream_t stream,
- bool uniforum, size_t page_width);
+ const char *charset, bool uniforum,
+ size_t page_width);
extern void
message_print_comment_flags (const message_ty *mp, ostream_t stream,
bool debug);
/* Writing Java .properties files.
- Copyright (C) 2003, 2005-2009, 2019 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2009, 2019, 2021 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
message_print_comment_dot (mp, stream);
/* Print the file position comments. */
- message_print_comment_filepos (mp, stream, false, page_width);
+ message_print_comment_filepos (mp, stream, po_charset_utf8, false,
+ page_width);
/* Print flag information in special comment. */
message_print_comment_flags (mp, stream, debug);
{
msgdomain_list_print_properties, /* print */
true, /* requires_utf8 */
+ true, /* requires_utf8_for_filenames_with_spaces */
false, /* supports_color */
false, /* supports_multiple_domains */
false, /* supports_contexts */
/* Writing NeXTstep/GNUstep .strings files.
- Copyright (C) 2003, 2006-2008, 2019 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2008, 2019, 2021 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
{
msgdomain_list_print_stringtable, /* print */
true, /* requires_utf8 */
+ false, /* requires_utf8_for_filenames_with_spaces */
false, /* supports_color */
false, /* supports_multiple_domains */
false, /* supports_contexts */
/* Extracts strings from C source file to Uniforum style .po file.
- Copyright (C) 1995-1998, 2000-2016, 2018-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2016, 2018-2021 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
#include "read-catalog-abstract.h"
#include "read-po.h"
#include "message.h"
+#include "pos.h"
#include "po-charset.h"
#include "msgl-iconv.h"
#include "msgl-ascii.h"
+#include "msgl-ofn.h"
#include "msgl-check.h"
#include "po-time.h"
#include "write-catalog.h"
All messages have already been converted to UTF-8 in remember_a_message
and remember_a_message_plural. */
{
- bool has_nonascii = false;
- size_t i;
-
- for (i = 0; i < mdlp->nitems; i++)
- {
- message_list_ty *mlp = mdlp->item[i]->messages;
-
- if (!is_ascii_message_list (mlp))
- has_nonascii = true;
- }
-
- if (has_nonascii || output_syntax->requires_utf8)
+ bool has_nonascii = ! is_ascii_msgdomain_list (mdlp);
+ bool has_filenames_with_spaces =
+ msgdomain_list_has_filenames_with_spaces (mdlp);
+
+ if (has_nonascii
+ || (has_filenames_with_spaces
+ && output_syntax->requires_utf8_for_filenames_with_spaces)
+ || output_syntax->requires_utf8)
{
message_list_ty *mlp = mdlp->item[0]->messages;
## Makefile for the gettext-tools/tests subdirectory of GNU gettext
-## Copyright (C) 1995-1997, 2001-2010, 2012-2016, 2018-2020 Free Software Foundation, Inc.
+## Copyright (C) 1995-1997, 2001-2010, 2012-2016, 2018-2021 Free Software Foundation, Inc.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
recode-sr-latin-1 recode-sr-latin-2 \
xgettext-2 xgettext-3 xgettext-4 xgettext-5 xgettext-6 \
xgettext-7 xgettext-8 xgettext-9 xgettext-10 xgettext-11 xgettext-12 \
- xgettext-13 xgettext-14 xgettext-15 xgettext-16 \
+ xgettext-13 xgettext-14 xgettext-15 xgettext-16 xgettext-17 \
xgettext-appdata-1 \
xgettext-awk-1 xgettext-awk-2 \
xgettext-c-2 xgettext-c-3 xgettext-c-4 xgettext-c-5 xgettext-c-6 \
--- /dev/null
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test file locations with file names that contain spaces.
+
+cat <<\EOF > 'xg-test17 a.c'
+gettext ("foo");
+EOF
+
+cat <<\EOF > 'xg-test17 x y.c'
+gettext ("foo");
+gettext ("bar");
+EOF
+
+cat <<\EOF > 'xg-test17z.c'
+gettext ("bar");
+EOF
+
+: ${XGETTEXT=xgettext}
+${XGETTEXT} 'xg-test17 a.c' 'xg-test17 x y.c' 'xg-test17z.c' \
+ -o xg-test17.out >xg-test17.err 2>&1
+result=$?
+cat xg-test17.err | grep -v '^ '
+test $result = 0 || { Exit 1; }
+sed -e '/\"POT-Creation-Date:.*/d' < xg-test17.out | LC_ALL=C tr -d '\r' > xg-test17.po
+
+cat <<\EOF > xg-test17.ok
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: xg-test17 a.c:1 xg-test17 x y.c:1
+msgid "foo"
+msgstr ""
+
+#: xg-test17 x y.c:2 xg-test17z.c:1
+msgid "bar"
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} xg-test17.ok xg-test17.po
+result=$?
+
+exit $result