Add format string checking facility to the gettextpo library.
+2004-09-06 Bruno Haible <bruno@clisp.org>
+
+ * windows/gettextpo.def: Add po_message_check_format.
+
2004-09-05 Bruno Haible <bruno@clisp.org>
* windows/gettextsrc.def: Add the variables names from po-error.h.
+2004-09-06 Bruno Haible <bruno@clisp.org>
+
+ * Makevars (XGETTEXT_OPTIONS): Recognize error_logger calls.
+
2004-09-05 Bruno Haible <bruno@clisp.org>
* Makevars (XGETTEXT_OPTIONS): Recognize po_error and po_error_at_line.
--keyword=N_ --flag=N_:1:pass-c-format \
--flag=error:3:c-format --flag=error_at_line:5:c-format \
--flag=asprintf:2:c-format --flag=vasprintf:2:c-format \
- --flag=xasprintf:1:c-format \
+ --flag=xasprintf:1:c-format --flag=error_logger:1:c-format \
--flag=po_error:3:c-format --flag=po_error_at_line:5:c-format \
--flag=po_gram_error:1:c-format --flag=po_gram_error_at_line:2:c-format
+2004-09-06 Bruno Haible <bruno@clisp.org>
+
+ * format.h (formatstring_error_logger_t): New type.
+ (struct formatstring_parser): Change calling convention of 'check'
+ method.
+ (check_msgid_msgstr_format): New declaration.
+ * format-awk.c (format_check): Use error_logger argument instead of
+ noisy and error_at_line.
+ * format-c.c (format_check): Likewise.
+ * format-csharp.c (format_check): Likewise.
+ * format-elisp.c (format_check): Likewise.
+ * format-gcc-internal.c (format_check): Likewise.
+ * format-java.c (format_check): Likewise.
+ * format-librep.c (format_check): Likewise.
+ * format-lisp.c (format_check): Likewise.
+ * format-pascal.c (format_check): Likewise.
+ * format-perl.c (format_check): Likewise.
+ * format-perl-brace.c (format_check): Likewise.
+ * format-php.c (format_check): Likewise.
+ * format-python.c (format_check): Likewise.
+ * format-qt.c (format_check): Likewise.
+ * format-sh.c (format_check): Likewise.
+ * format-tcl.c (format_check): Likewise.
+ * format-ycp.c (format_check): Likewise.
+ * format.c (check_msgid_msgstr_format): New function, extracted from
+ msgfmt.c.
+ * msgfmt.c (curr_msgid_pos): New variable.
+ (formatstring_error_logger): New function.
+ (check_pair): Use check_msgid_msgstr_format, formatstring_error_logger.
+ * msgmerge.c (msgfmt_check_pair_fails): Update.
+ * gettext-po.h (po_message_check_format): New declaration.
+ * gettext-po.c (po_error_logger, po_message_check_format): New
+ functions.
+
2004-09-05 Bruno Haible <bruno@clisp.org>
* po-error.h: New file.
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
: spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("number of format specifications in 'msgid' and '%s' does not match"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
+ pretty_msgstr);
err = true;
}
else
for (i = 0; i < spec2->unnumbered_arg_count; i++)
if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr, i + 1);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, i + 1);
err = true;
}
#include "c-ctype.h"
#include "xalloc.h"
#include "xerror.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
? spec1->numbered_arg_count != spec2->numbered_arg_count
: spec1->numbered_arg_count < spec2->numbered_arg_count)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("number of format specifications in 'msgid' and '%s' does not match"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
+ pretty_msgstr);
err = true;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
: spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("number of format specifications in 'msgid' and '%s' does not match"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
+ pretty_msgstr);
err = true;
}
else
for (i = 0; i < spec2->unnumbered_arg_count; i++)
if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr, i + 1);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, i + 1);
err = true;
}
#include "xallocsa.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument {%u}, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument {%u}, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument {%u} doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument {%u} doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument {%u} are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument {%u} are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xerror.h"
#include "format-invalid.h"
#include "minmax.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
{
if (!equal_list (spec1->list, spec2->list))
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' are not equivalent"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' are not equivalent"),
+ pretty_msgstr);
err = true;
}
}
&& (normalize_list (intersection),
equal_list (intersection, spec2->list))))
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in '%s' are not a subset of those in 'msgid'"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in '%s' are not a subset of those in 'msgid'"),
+ pretty_msgstr);
err = true;
}
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "format.h"
#include "xalloc.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument '%s' doesn't exist in '%s'"),
- spec1->named[i].name, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument '%s' doesn't exist in '%s'"),
+ spec1->named[i].name, pretty_msgstr);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (spec1->named_arg_count > 0 && spec2->unnamed_arg_count > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' expect a mapping, those in '%s' expect a tuple"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' expect a mapping, those in '%s' expect a tuple"),
+ pretty_msgstr);
err = true;
}
else if (spec1->unnamed_arg_count > 0 && spec2->named_arg_count > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' expect a tuple, those in '%s' expect a mapping"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' expect a tuple, those in '%s' expect a mapping"),
+ pretty_msgstr);
err = true;
}
else
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument '%s', as in '%s', doesn't exist in 'msgid'"),
- spec2->named[j].name, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument '%s', as in '%s', doesn't exist in 'msgid'"),
+ spec2->named[j].name, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument '%s' doesn't exist in '%s'"),
- spec1->named[i].name, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument '%s' doesn't exist in '%s'"),
+ spec1->named[i].name, pretty_msgstr);
err = true;
break;
}
{
if (spec1->named[i].type != spec2->named[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name,
- pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument '%s' are not the same"),
- pretty_msgstr,
- spec2->named[j].name);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument '%s' are not the same"),
+ pretty_msgstr, spec2->named[j].name);
err = true;
break;
}
? spec1->unnamed_arg_count != spec2->unnamed_arg_count
: spec1->unnamed_arg_count < spec2->unnamed_arg_count)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("number of format specifications in 'msgid' and '%s' does not match"),
- pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
+ pretty_msgstr);
err = true;
}
else
for (i = 0; i < spec2->unnamed_arg_count; i++)
if (spec1->unnamed[i].type != spec2->unnamed[i].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr, i + 1);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, i + 1);
err = true;
}
}
#include "format.h"
#include "xalloc.h"
#include "xerror.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
yield a "Argument missing" warning at runtime. */
if (arg_used1 != arg_used2)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- arg_used1
- ? _("a format specification for argument %u doesn't exist in '%s'")
- : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- i, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (arg_used1
+ ? _("a format specification for argument %u doesn't exist in '%s'")
+ : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ i, pretty_msgstr);
err = true;
break;
}
#include "c-ctype.h"
#include "xalloc.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument '%s', as in '%s', doesn't exist in 'msgid'"),
- spec2->named[j].name, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument '%s', as in '%s', doesn't exist in 'msgid'"),
+ spec2->named[j].name, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument '%s' doesn't exist in '%s'"),
- spec1->named[i].name, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument '%s' doesn't exist in '%s'"),
+ spec1->named[i].name, pretty_msgstr);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (cmp > 0)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- spec2->numbered[j].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ spec2->numbered[j].number, pretty_msgstr);
err = true;
break;
}
{
if (equality)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("a format specification for argument %u doesn't exist in '%s'"),
- spec1->numbered[i].number, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("a format specification for argument %u doesn't exist in '%s'"),
+ spec1->numbered[i].number, pretty_msgstr);
err = true;
break;
}
{
if (spec1->numbered[i].type != spec2->numbered[j].type)
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- _("format specifications in 'msgid' and '%s' for argument %u are not the same"),
- pretty_msgstr,
- spec2->numbered[j].number);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
+ pretty_msgstr, spec2->numbered[j].number);
err = true;
break;
}
#include "xalloc.h"
#include "xerror.h"
#include "format-invalid.h"
-#include "error.h"
-#include "error-progname.h"
#include "gettext.h"
#define _(str) gettext (str)
}
static bool
-format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
- bool equality, bool noisy, const char *pretty_msgstr)
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgstr)
{
struct spec *spec1 = (struct spec *) msgid_descr;
struct spec *spec2 = (struct spec *) msgstr_descr;
if (equality ? (arg_used1 != arg_used2) : (!arg_used1 && arg_used2))
{
- if (noisy)
- {
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number,
- arg_used1
- ? _("a format specification for argument %u doesn't exist in '%s'")
- : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
- i + 1, pretty_msgstr);
- error_with_progname = true;
- }
+ if (error_logger)
+ error_logger (arg_used1
+ ? _("a format specification for argument %u doesn't exist in '%s'")
+ : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+ i + 1, pretty_msgstr);
err = true;
break;
}
/* 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
/* Specification. */
#include "format.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "message.h"
+#include "gettext.h"
+
+#define _(str) gettext (str)
+
/* Table of all format string parsers. */
struct formatstring_parser *formatstring_parsers[NFORMATS] =
{
/* format_gcc_internal */ &formatstring_gcc_internal,
/* format_qt */ &formatstring_qt
};
+
+/* Check whether both formats strings contain compatible format
+ specifications. Return true if there is an error. */
+bool
+check_msgid_msgstr_format (const char *msgid, const char *msgid_plural,
+ const char *msgstr, size_t msgstr_len,
+ enum is_format is_format[NFORMATS],
+ formatstring_error_logger_t error_logger)
+{
+ bool err = false;
+ size_t i;
+ unsigned int j;
+
+ /* We check only those messages for which the msgid's is_format flag
+ is one of 'yes' or 'possible'. We don't check msgids with is_format
+ 'no' or 'impossible', to obey the programmer's order. We don't check
+ msgids with is_format 'undecided' because that would introduce too
+ many checks, thus forcing the programmer to add "xgettext: no-c-format"
+ anywhere where a translator wishes to use a percent sign. */
+ for (i = 0; i < NFORMATS; i++)
+ if (possible_format_p (is_format[i]))
+ {
+ /* At runtime, we can assume the program passes arguments that
+ fit well for msgid. We must signal an error if msgstr wants
+ more arguments that msgid accepts.
+ If msgstr wants fewer arguments than msgid, it wouldn't lead
+ to a crash at runtime, but we nevertheless give an error because
+ 1) this situation occurs typically after the programmer has
+ added some arguments to msgid, so we must make the translator
+ specially aware of it (more than just "fuzzy"),
+ 2) it is generally wrong if a translation wants to ignore
+ arguments that are used by other translations. */
+
+ struct formatstring_parser *parser = formatstring_parsers[i];
+ char *invalid_reason = NULL;
+ void *msgid_descr =
+ parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
+ false, &invalid_reason);
+
+ if (msgid_descr != NULL)
+ {
+ char buf[18+1];
+ const char *pretty_msgstr = "msgstr";
+ const char *p_end = msgstr + msgstr_len;
+ const char *p;
+
+ for (p = msgstr, j = 0; p < p_end; p += strlen (p) + 1, j++)
+ {
+ void *msgstr_descr;
+
+ if (msgid_plural != NULL)
+ {
+ sprintf (buf, "msgstr[%u]", j);
+ pretty_msgstr = buf;
+ }
+
+ msgstr_descr = parser->parse (p, true, &invalid_reason);
+
+ if (msgstr_descr != NULL)
+ {
+ if (parser->check (msgid_descr, msgstr_descr,
+ msgid_plural == NULL,
+ error_logger, pretty_msgstr))
+ err = true;
+
+ parser->free (msgstr_descr);
+ }
+ else
+ {
+ error_logger (_("\
+'%s' is not a valid %s format string, unlike 'msgid'. Reason: %s"),
+ pretty_msgstr, format_language_pretty[i],
+ invalid_reason);
+ err = true;
+ free (invalid_reason);
+ }
+ }
+
+ parser->free (msgid_descr);
+ }
+ else
+ free (invalid_reason);
+ }
+
+ return err;
+}
#include "pos.h" /* Get lex_pos_ty. */
#include "message.h" /* Get NFORMATS. */
+#include "error.h" /* Get fallback definition of __attribute__. */
#ifdef __cplusplus
#endif
+/* This type of callback is responsible for showing an error. */
+typedef void (*formatstring_error_logger_t) (const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
+
/* This structure describes a format string parser for a language. */
struct formatstring_parser
{
msgstr_descr are the same (if equality=true), or (if equality=false)
that those of msgid_descr extend those of msgstr_descr (i.e.
msgstr_descr may omit some of the arguments of msgid_descr).
- If not, signal an error using
- error_with_progname = false;
- error_at_line (0, 0, pos->file_name, pos->line_number, ...);
- error_with_progname = true;
- (but only if noisy=true) and return true. Otherwise return false. */
- bool (*check) (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr, bool equality, bool noisy, const char *pretty_msgstr);
+ If not, signal an error using error_logger (only if error_logger != NULL)
+ and return true. Otherwise return false. */
+ bool (*check) (void *msgid_descr, void *msgstr_descr, bool equality, formatstring_error_logger_t error_logger, const char *pretty_msgstr);
};
/* Format string parsers, each defined in its own file. */
get_sysdep_c_format_directives (const char *string, bool translated,
struct interval **intervalsp, size_t *lengthp);
+/* Check whether both formats strings contain compatible format
+ specifications. Return true if there is an error. */
+extern bool
+ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural,
+ const char *msgstr, size_t msgstr_len,
+ enum is_format is_format[NFORMATS],
+ formatstring_error_logger_t error_logger);
+
#ifdef __cplusplus
}
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include "message.h"
#include "xalloc.h"
#include "error.h"
#include "xerror.h"
#include "po-error.h"
+#include "vasprintf.h"
+#include "format.h"
#include "gettext.h"
#define _(str) gettext(str)
}
-#if 0
-/* Test whether the message translation is a valid format string if the message
- is marked as being a format string. Return NULL if valid or not marked as
- such, or an explanation string if invalid. */
+/* An error logger based on the po_error function pointer. */
+static void
+po_error_logger (const char *format, ...)
+{
+ va_list args;
+ char *error_message;
-char *
-po_message_check_format (po_message_t message, const char *format_type)
+ va_start (args, format);
+ if (vasprintf (&error_message, format, args) < 0)
+ error (EXIT_FAILURE, 0, _("memory exhausted"));
+ va_end (args);
+ po_error (0, 0, "%s", error_message);
+ free (error_message);
+}
+
+/* Test whether the message translation is a valid format string if the message
+ is marked as being a format string. If it is invalid, pass the reasons to
+ the handler. */
+void
+po_message_check_format (po_message_t message, po_error_handler_t handler)
{
- ??
+ message_ty *mp = (message_ty *) message;
+
+ /* Establish error handler for po_error_logger(). */
+ po_error = handler->error;
+
+ check_msgid_msgstr_format (mp->msgid, mp->msgid_plural,
+ mp->msgstr, mp->msgstr_len,
+ mp->is_format, po_error_logger);
+
+ /* Restore error handler. */
+ po_error = error;
}
-#endif
/* Return the file name. */
/* Change the format string mark for a given type of a message. */
extern void po_message_set_format (po_message_t message, const char *format_type, /*bool*/int value);
-#if 0
/* Test whether the message translation is a valid format string if the message
- is marked as being a format string. Return NULL if valid or not marked as
- such, or an explanation string if invalid. */
-extern char * po_message_check_format (po_message_t message, const char *format_type);
-#endif
+ is marked as being a format string. If it is invalid, pass the reasons to
+ the handler. */
+extern void po_message_check_format (po_message_t message, po_error_handler_t handler);
/* =========================== po_filepos_t API ============================ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <locale.h>
#include "closeout.h"
}
+/* Signal an error when checking format strings. */
+static lex_pos_ty curr_msgid_pos;
+static void
+formatstring_error_logger (const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ fprintf (stderr, "%s:%d: ",
+ curr_msgid_pos.file_name, curr_msgid_pos.line_number);
+ vfprintf (stderr, format, args);
+ putc ('\n', stderr);
+ fflush (stderr);
+ va_end (args);
+ ++error_message_count;
+}
+
+
/* Perform miscellaneous checks on a message. */
static void
check_pair (const char *msgid,
const lex_pos_ty *msgstr_pos, enum is_format is_format[NFORMATS])
{
int has_newline;
- size_t i;
unsigned int j;
const char *p;
if (check_format_strings)
/* Test 3: Check whether both formats strings contain the same number
- of format specifications.
- We check only those messages for which the msgid's is_format flag
- is one of 'yes' or 'possible'. We don't check msgids with is_format
- 'no' or 'impossible', to obey the programmer's order. We don't check
- msgids with is_format 'undecided' because that would introduce too
- many checks, thus forcing the programmer to add "xgettext: no-c-format"
- anywhere where a translator wishes to use a percent sign. */
- for (i = 0; i < NFORMATS; i++)
- if (possible_format_p (is_format[i]))
- {
- /* At runtime, we can assume the program passes arguments that
- fit well for msgid. We must signal an error if msgstr wants
- more arguments that msgid accepts.
- If msgstr wants fewer arguments than msgid, it wouldn't lead
- to a crash at runtime, but we nevertheless give an error because
- 1) this situation occurs typically after the programmer has
- added some arguments to msgid, so we must make the translator
- specially aware of it (more than just "fuzzy"),
- 2) it is generally wrong if a translation wants to ignore
- arguments that are used by other translations. */
-
- struct formatstring_parser *parser = formatstring_parsers[i];
- char *invalid_reason = NULL;
- void *msgid_descr =
- parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
- false, &invalid_reason);
-
- if (msgid_descr != NULL)
- {
- char buf[18+1];
- const char *pretty_msgstr = "msgstr";
- const char *p_end = msgstr + msgstr_len;
- const char *p;
-
- for (p = msgstr, j = 0; p < p_end; p += strlen (p) + 1, j++)
- {
- void *msgstr_descr;
-
- if (msgid_plural != NULL)
- {
- sprintf (buf, "msgstr[%u]", j);
- pretty_msgstr = buf;
- }
-
- msgstr_descr = parser->parse (p, true, &invalid_reason);
-
- if (msgstr_descr != NULL)
- {
- if (parser->check (msgid_pos, msgid_descr, msgstr_descr,
- msgid_plural == NULL,
- true, pretty_msgstr))
- exit_status = EXIT_FAILURE;
-
- parser->free (msgstr_descr);
- }
- else
- {
- error_with_progname = false;
- error_at_line (0, 0, msgid_pos->file_name,
- msgid_pos->line_number,
- _("\
-'%s' is not a valid %s format string, unlike 'msgid'. Reason: %s"),
- pretty_msgstr, format_language_pretty[i],
- invalid_reason);
- error_with_progname = true;
- exit_status = EXIT_FAILURE;
- free (invalid_reason);
- }
- }
-
- parser->free (msgid_descr);
- }
- else
- free (invalid_reason);
- }
+ of format specifications. */
+ {
+ curr_msgid_pos = *msgid_pos;
+ if (check_msgid_msgstr_format (msgid, msgid_plural, msgstr, msgstr_len,
+ is_format, formatstring_error_logger))
+ exit_status = EXIT_FAILURE;
+ }
if (check_accelerators && msgid_plural == NULL)
/* Test 4: Check that if msgid is a menu item with a keyboard accelerator,
if (msgstr_descr != NULL)
{
- failure = parser->check (pos, msgid_descr, msgstr_descr,
- msgid_plural == NULL, false, NULL);
+ failure = parser->check (msgid_descr, msgstr_descr,
+ msgid_plural == NULL, NULL, NULL);
parser->free (msgstr_descr);
}
else
po_filepos_file
po_filepos_start_line
po_header_field
+po_message_check_format
po_message_comments
po_message_create
po_message_extracted_comments