struct spec
{
unsigned int directives;
+ /* We consider a directive as "likely intentional" if it does not contain a
+ space. This prevents xgettext from flagging strings like "100% complete"
+ as 'c-format' if they don't occur in a context that requires a format
+ string. */
+ unsigned int likely_intentional_directives;
unsigned int unnumbered_arg_count;
struct unnumbered_arg *unnumbered;
bool unlikely_intentional;
unsigned int allocated;
spec.directives = 0;
+ spec.likely_intentional_directives = 0;
spec.unnumbered_arg_count = 0;
spec.unnumbered = NULL;
spec.unlikely_intentional = false;
format_arg_type_t integer_size;
/* Relevant for the conversion characters a, A, e, E, f, F, g, G. */
format_arg_type_t floatingpoint_size;
+ bool likely_intentional = true;
FDI_SET (format - 1, FMTDIR_START);
spec.directives++;
{
if (*format == ' ' || *format == '+' || *format == '-'
|| *format == '#' || *format == '0' || *format == '\'')
- format++;
+ {
+ if (*format == ' ')
+ likely_intentional = false;
+ format++;
+ }
#if HANDLE_I_FLAG
else if (translated && *format == 'I')
{
}
}
+ if (likely_intentional)
+ spec.likely_intentional_directives++;
FDI_SET (format, FMTDIR_END);
format++;
/* C format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009-2010, 2019, 2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2025 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
free (spec);
}
-static bool
-format_is_unlikely_intentional (void *descr)
+static int
+format_get_number_of_directives (void *descr)
{
struct spec *spec = (struct spec *) descr;
- return spec->unlikely_intentional;
+ return spec->directives;
}
-static int
-format_get_number_of_directives (void *descr)
+static bool
+format_is_unlikely_intentional (void *descr)
{
struct spec *spec = (struct spec *) descr;
- return spec->directives;
+ return spec->likely_intentional_directives == 0 || spec->unlikely_intentional;
}
static bool
xgettext-ycp-stackovfl-3 xgettext-ycp-stackovfl-4 \
format-awk-1 format-awk-2 format-awk-3 \
format-boost-1 format-boost-2 \
- format-c-1 format-c-2 format-c-3 format-c-4 format-c-5 \
+ format-c-1 format-c-2 format-c-3 format-c-4 format-c-5 format-c-6 \
format-c++-brace-1 format-c++-brace-2 \
format-csharp-1 format-csharp-2 \
format-d-1 format-d-2 \
--- /dev/null
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test heuristic recognition of C format strings like "100% complete".
+
+cat <<\EOF > f-c-6.c
+gettext("Test 1a is 100% complete");
+printf(gettext("Test 1b is 100% complete"), 120);
+gettext("Test 2a from 0% complete to 100% complete");
+printf(gettext("Test 2b from 0% complete to 100% complete"), 120, 121);
+gettext("Test 3a of %s is 100% complete");
+printf(gettext("Test 3b of %s is 100% complete"), "foo", 120);
+EOF
+
+: ${XGETTEXT=xgettext}
+${XGETTEXT} --omit-header --no-location -d f-c-6.tmp f-c-6.c || Exit 1
+LC_ALL=C tr -d '\r' < f-c-6.tmp.po > f-c-6.po || Exit 1
+
+cat <<\EOF > f-c-6.ok
+msgid "Test 1a is 100% complete"
+msgstr ""
+
+#, c-format
+msgid "Test 1b is 100% complete"
+msgstr ""
+
+msgid "Test 2a from 0% complete to 100% complete"
+msgstr ""
+
+#, c-format
+msgid "Test 2b from 0% complete to 100% complete"
+msgstr ""
+
+#, c-format
+msgid "Test 3a of %s is 100% complete"
+msgstr ""
+
+#, c-format
+msgid "Test 3b of %s is 100% complete"
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} f-c-6.ok f-c-6.po
+result=$?
+
+exit $result