1 /* Checking of messages in PO files.
2 Copyright (C) 1995-1998, 2000-2008, 2010-2015 Free Software
4 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "msgl-check.h"
36 #include "xvasprintf.h"
37 #include "po-xerror.h"
39 #include "plural-exp.h"
40 #include "plural-eval.h"
41 #include "plural-table.h"
50 #define _(str) gettext (str)
52 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
55 /* Evaluates the plural formula for min <= n <= max
56 and returns the estimated number of times the value j was assumed. */
58 plural_expression_histogram (const struct plural_distribution *self,
59 int min, int max, unsigned long j)
63 /* Limit the number of evaluations. Nothing interesting happens beyond
69 const struct expression *expr = self->expr;
73 /* Protect against arithmetic exceptions. */
74 install_sigfpe_handler ();
77 for (n = min; n <= max; n++)
79 unsigned long val = plural_eval (expr, n);
85 /* End of protection against arithmetic exceptions. */
86 uninstall_sigfpe_handler ();
95 /* Check the values returned by plural_eval.
96 Signals the errors through po_xerror.
97 Return the number of errors that were seen.
98 If no errors, returns in *DISTRIBUTION information about the plural_eval
99 values distribution. */
101 check_plural_eval (const struct expression *plural_expr,
102 unsigned long nplurals_value,
103 const message_ty *header,
104 struct plural_distribution *distribution)
106 /* Do as if the plural formula assumes a value N infinitely often if it
107 assumes it at least 5 times. */
109 unsigned char * volatile array;
111 /* Allocate a distribution array. */
112 if (nplurals_value <= 100)
113 array = XCALLOC (nplurals_value, unsigned char);
115 /* nplurals_value is nonsense. Don't risk an out-of-memory. */
118 if (sigsetjmp (sigfpe_exit, 1) == 0)
122 /* Protect against arithmetic exceptions. */
123 install_sigfpe_handler ();
125 for (n = 0; n <= 1000; n++)
127 unsigned long val = plural_eval (plural_expr, n);
131 /* End of protection against arithmetic exceptions. */
132 uninstall_sigfpe_handler ();
134 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
135 _("plural expression can produce negative values"));
139 else if (val >= nplurals_value)
143 /* End of protection against arithmetic exceptions. */
144 uninstall_sigfpe_handler ();
146 msg = xasprintf (_("nplurals = %lu but plural expression can produce values as large as %lu"),
147 nplurals_value, val);
148 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
154 if (array != NULL && array[val] < OFTEN)
158 /* End of protection against arithmetic exceptions. */
159 uninstall_sigfpe_handler ();
161 /* Normalize the array[val] statistics. */
166 for (val = 0; val < nplurals_value; val++)
167 array[val] = (array[val] == OFTEN ? 1 : 0);
170 distribution->expr = plural_expr;
171 distribution->often = array;
172 distribution->often_length = (array != NULL ? nplurals_value : 0);
173 distribution->histogram = plural_expression_histogram;
179 /* Caught an arithmetic exception. */
182 /* End of protection against arithmetic exceptions. */
183 uninstall_sigfpe_handler ();
192 msg = _("plural expression can produce division by zero");
197 msg = _("plural expression can produce integer overflow");
202 msg = _("plural expression can produce arithmetic exceptions, possibly division by zero");
205 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
215 /* Try to help the translator by looking up the right plural formula for her.
216 Return a freshly allocated multiline help string, or NULL. */
218 plural_help (const char *nullentry)
220 struct plural_table_entry *ptentry = NULL;
223 const char *language;
225 language = c_strstr (nullentry, "Language: ");
226 if (language != NULL)
231 len = strcspn (language, " \t\n");
236 for (j = 0; j < plural_table_size; j++)
237 if (len == strlen (plural_table[j].lang)
238 && strncmp (language, plural_table[j].lang, len) == 0)
240 ptentry = &plural_table[j];
249 const char *language;
251 language = c_strstr (nullentry, "Language-Team: ");
252 if (language != NULL)
257 for (j = 0; j < plural_table_size; j++)
258 if (strncmp (language,
259 plural_table[j].language,
260 strlen (plural_table[j].language)) == 0)
262 ptentry = &plural_table[j];
271 xasprintf (_("Try using the following, valid for %s:"),
274 xasprintf ("%s\n\"Plural-Forms: %s\\n\"\n",
275 helpline1, ptentry->value);
283 /* Perform plural expression checking.
284 Return the number of errors that were seen.
285 If no errors, returns in *DISTRIBUTION information about the plural_eval
286 values distribution. */
288 check_plural (message_list_ty *mlp,
289 int ignore_untranslated_messages,
290 int ignore_fuzzy_messages,
291 struct plural_distribution *distributionp)
294 const message_ty *has_plural;
295 unsigned long min_nplurals;
296 const message_ty *min_pos;
297 unsigned long max_nplurals;
298 const message_ty *max_pos;
299 struct plural_distribution distribution;
303 /* Determine whether mlp has plural entries. */
305 min_nplurals = ULONG_MAX;
309 distribution.expr = NULL;
310 distribution.often = NULL;
311 distribution.often_length = 0;
312 distribution.histogram = NULL;
313 for (j = 0; j < mlp->nitems; j++)
315 message_ty *mp = mlp->item[j];
318 && !(ignore_untranslated_messages && mp->msgstr[0] == '\0')
319 && !(ignore_fuzzy_messages && (mp->is_fuzzy && !is_header (mp)))
320 && mp->msgid_plural != NULL)
326 if (has_plural == NULL)
330 for (p = mp->msgstr, p_end = p + mp->msgstr_len;
334 if (min_nplurals > n)
339 if (max_nplurals < n)
347 /* Look at the plural entry for this domain.
348 Cf, function extract_plural_expression. */
349 header = message_list_search (mlp, NULL, "");
350 if (header != NULL && !header->obsolete)
352 const char *nullentry;
354 const char *nplurals;
356 nullentry = header->msgstr;
358 plural = c_strstr (nullentry, "plural=");
359 nplurals = c_strstr (nullentry, "nplurals=");
360 if (plural == NULL && has_plural != NULL)
363 _("message catalog has plural form translations");
365 _("but header entry lacks a \"plural=EXPRESSION\" attribute");
366 char *help = plural_help (nullentry);
370 char *msg2ext = xasprintf ("%s\n%s", msg2, help);
371 po_xerror2 (PO_SEVERITY_ERROR,
372 has_plural, NULL, 0, 0, false, msg1,
373 header, NULL, 0, 0, true, msg2ext);
378 po_xerror2 (PO_SEVERITY_ERROR,
379 has_plural, NULL, 0, 0, false, msg1,
380 header, NULL, 0, 0, false, msg2);
384 if (nplurals == NULL && has_plural != NULL)
387 _("message catalog has plural form translations");
389 _("but header entry lacks a \"nplurals=INTEGER\" attribute");
390 char *help = plural_help (nullentry);
394 char *msg2ext = xasprintf ("%s\n%s", msg2, help);
395 po_xerror2 (PO_SEVERITY_ERROR,
396 has_plural, NULL, 0, 0, false, msg1,
397 header, NULL, 0, 0, true, msg2ext);
402 po_xerror2 (PO_SEVERITY_ERROR,
403 has_plural, NULL, 0, 0, false, msg1,
404 header, NULL, 0, 0, false, msg2);
408 if (plural != NULL && nplurals != NULL)
411 unsigned long int nplurals_value;
412 struct parse_args args;
413 const struct expression *plural_expr;
415 /* First check the number. */
417 while (*nplurals != '\0' && c_isspace ((unsigned char) *nplurals))
421 if (*nplurals >= '0' && *nplurals <= '9')
422 nplurals_value = strtoul (nplurals, (char **) &endp, 10);
423 if (nplurals == endp)
425 const char *msg = _("invalid nplurals value");
426 char *help = plural_help (nullentry);
430 char *msgext = xasprintf ("%s\n%s", msg, help);
431 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, true,
437 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
442 /* Then check the expression. */
445 if (parse_plural_expression (&args) != 0)
447 const char *msg = _("invalid plural expression");
448 char *help = plural_help (nullentry);
452 char *msgext = xasprintf ("%s\n%s", msg, help);
453 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, true,
459 po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
463 plural_expr = args.res;
465 /* See whether nplurals and plural fit together. */
468 check_plural_eval (plural_expr, nplurals_value, header,
471 /* Check the number of plurals of the translations. */
474 if (min_nplurals < nplurals_value)
477 xasprintf (_("nplurals = %lu"), nplurals_value);
479 xasprintf (ngettext ("but some messages have only one plural form",
480 "but some messages have only %lu plural forms",
483 po_xerror2 (PO_SEVERITY_ERROR,
484 header, NULL, 0, 0, false, msg1,
485 min_pos, NULL, 0, 0, false, msg2);
490 else if (max_nplurals > nplurals_value)
493 xasprintf (_("nplurals = %lu"), nplurals_value);
495 xasprintf (ngettext ("but some messages have one plural form",
496 "but some messages have %lu plural forms",
499 po_xerror2 (PO_SEVERITY_ERROR,
500 header, NULL, 0, 0, false, msg1,
501 max_pos, NULL, 0, 0, false, msg2);
506 /* The only valid case is max_nplurals <= n <= min_nplurals,
507 which means either has_plural == NULL or
508 max_nplurals = n = min_nplurals. */
516 if (has_plural != NULL)
518 po_xerror (PO_SEVERITY_ERROR, has_plural, NULL, 0, 0, false,
519 _("message catalog has plural form translations, but lacks a header entry with \"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\""));
523 /* By default, the Germanic formula (n != 1) is used. */
524 distribution.expr = &germanic_plural;
526 unsigned char *array = XCALLOC (2, unsigned char);
528 distribution.often = array;
530 distribution.often_length = 2;
531 distribution.histogram = plural_expression_histogram;
534 /* distribution is not needed if we report errors.
535 Also, if there was an error due to max_nplurals > nplurals_value,
536 we must not use distribution because we would be doing out-of-bounds
539 free ((unsigned char *) distribution.often);
541 *distributionp = distribution;
547 /* Signal an error when checking format strings. */
548 static const message_ty *curr_mp;
549 static lex_pos_ty curr_msgid_pos;
551 formatstring_error_logger (const char *format, ...)
552 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ > 2)
553 __attribute__ ((__format__ (__printf__, 1, 2)))
557 formatstring_error_logger (const char *format, ...)
562 va_start (args, format);
563 if (vasprintf (&msg, format, args) < 0)
564 error (EXIT_FAILURE, 0, _("memory exhausted"));
566 po_xerror (PO_SEVERITY_ERROR,
567 curr_mp, curr_msgid_pos.file_name, curr_msgid_pos.line_number,
568 (size_t)(-1), false, msg);
573 /* Perform miscellaneous checks on a message.
574 PLURAL_DISTRIBUTION is either NULL or an array of nplurals elements,
575 PLURAL_DISTRIBUTION[j] being true if the value j appears to be assumed
576 infinitely often by the plural formula.
577 PLURAL_DISTRIBUTION_LENGTH is the length of the PLURAL_DISTRIBUTION
580 check_pair (const message_ty *mp,
582 const lex_pos_ty *msgid_pos,
583 const char *msgid_plural,
584 const char *msgstr, size_t msgstr_len,
585 const enum is_format is_format[NFORMATS],
587 int check_format_strings,
588 const struct plural_distribution *distribution,
589 int check_compatibility,
590 int check_accelerators, char accelerator_char)
596 /* If the msgid string is empty we have the special entry reserved for
597 information about the translation. */
598 if (msgid[0] == '\0')
605 /* Test 1: check whether all or none of the strings begin with a '\n'. */
606 has_newline = (msgid[0] == '\n');
607 #define TEST_NEWLINE(p) (p[0] == '\n')
608 if (msgid_plural != NULL)
612 if (TEST_NEWLINE(msgid_plural) != has_newline)
614 po_xerror (PO_SEVERITY_ERROR,
615 mp, msgid_pos->file_name, msgid_pos->line_number,
616 (size_t)(-1), false, _("\
617 'msgid' and 'msgid_plural' entries do not both begin with '\\n'"));
620 for (p = msgstr, j = 0; p < msgstr + msgstr_len; p += strlen (p) + 1, j++)
621 if (TEST_NEWLINE(p) != has_newline)
625 'msgid' and 'msgstr[%u]' entries do not both begin with '\\n'"), j);
626 po_xerror (PO_SEVERITY_ERROR,
627 mp, msgid_pos->file_name, msgid_pos->line_number,
628 (size_t)(-1), false, msg);
635 if (TEST_NEWLINE(msgstr) != has_newline)
637 po_xerror (PO_SEVERITY_ERROR,
638 mp, msgid_pos->file_name, msgid_pos->line_number,
639 (size_t)(-1), false, _("\
640 'msgid' and 'msgstr' entries do not both begin with '\\n'"));
646 /* Test 2: check whether all or none of the strings end with a '\n'. */
647 has_newline = (msgid[strlen (msgid) - 1] == '\n');
648 #define TEST_NEWLINE(p) (p[0] != '\0' && p[strlen (p) - 1] == '\n')
649 if (msgid_plural != NULL)
653 if (TEST_NEWLINE(msgid_plural) != has_newline)
655 po_xerror (PO_SEVERITY_ERROR,
656 mp, msgid_pos->file_name, msgid_pos->line_number,
657 (size_t)(-1), false, _("\
658 'msgid' and 'msgid_plural' entries do not both end with '\\n'"));
661 for (p = msgstr, j = 0; p < msgstr + msgstr_len; p += strlen (p) + 1, j++)
662 if (TEST_NEWLINE(p) != has_newline)
666 'msgid' and 'msgstr[%u]' entries do not both end with '\\n'"), j);
667 po_xerror (PO_SEVERITY_ERROR,
668 mp, msgid_pos->file_name, msgid_pos->line_number,
669 (size_t)(-1), false, msg);
676 if (TEST_NEWLINE(msgstr) != has_newline)
678 po_xerror (PO_SEVERITY_ERROR,
679 mp, msgid_pos->file_name, msgid_pos->line_number,
680 (size_t)(-1), false, _("\
681 'msgid' and 'msgstr' entries do not both end with '\\n'"));
688 if (check_compatibility && msgid_plural != NULL)
690 po_xerror (PO_SEVERITY_ERROR,
691 mp, msgid_pos->file_name, msgid_pos->line_number,
692 (size_t)(-1), false, _("\
693 plural handling is a GNU gettext extension"));
697 if (check_format_strings)
698 /* Test 3: Check whether both formats strings contain the same number
699 of format specifications. */
702 curr_msgid_pos = *msgid_pos;
704 check_msgid_msgstr_format (msgid, msgid_plural, msgstr, msgstr_len,
705 is_format, mp->range, distribution,
706 formatstring_error_logger);
709 if (check_accelerators && msgid_plural == NULL)
710 /* Test 4: Check that if msgid is a menu item with a keyboard accelerator,
711 the msgstr has an accelerator as well. A keyboard accelerator is
712 designated by an immediately preceding '&'. We cannot check whether
713 two accelerators collide, only whether the translator has bothered
714 thinking about them. */
718 /* We are only interested in msgids that contain exactly one '&'. */
719 p = strchr (msgid, accelerator_char);
720 if (p != NULL && strchr (p + 1, accelerator_char) == NULL)
722 /* Count the number of '&' in msgstr, but ignore '&&'. */
723 unsigned int count = 0;
725 for (p = msgstr; (p = strchr (p, accelerator_char)) != NULL; p++)
726 if (p[1] == accelerator_char)
734 xasprintf (_("msgstr lacks the keyboard accelerator mark '%c'"),
736 po_xerror (PO_SEVERITY_ERROR,
737 mp, msgid_pos->file_name, msgid_pos->line_number,
738 (size_t)(-1), false, msg);
745 xasprintf (_("msgstr has too many keyboard accelerator marks '%c'"),
747 po_xerror (PO_SEVERITY_ERROR,
748 mp, msgid_pos->file_name, msgid_pos->line_number,
749 (size_t)(-1), false, msg);
760 /* Perform miscellaneous checks on a header entry. */
762 check_header_entry (const message_ty *mp, const char *msgstr_string)
764 static const char *required_fields[] =
766 "Project-Id-Version", "PO-Revision-Date", "Last-Translator",
767 "Language-Team", "MIME-Version", "Content-Type",
768 "Content-Transfer-Encoding",
769 /* These are recommended but not yet required. */
772 static const char *default_values[] =
774 "PACKAGE VERSION", "YEAR-MO-DA HO:MI+ZONE", "FULL NAME <EMAIL@ADDRESS>", "LANGUAGE <LL@li.org>", NULL,
775 "text/plain; charset=CHARSET", "ENCODING",
778 const size_t nfields = SIZEOF (required_fields);
779 /* FIXME: We could check if a required header field is missing and
780 report it as error. However, it's could be too rigorous and
781 break backward compatibility. */
783 const size_t nrequiredfields = nfields - 1;
788 for (cnt = 0; cnt < nfields; ++cnt)
792 (cnt < nrequiredfields ? PO_SEVERITY_ERROR : PO_SEVERITY_WARNING);
797 const char *field = required_fields[cnt];
798 size_t len = strlen (field);
801 for (line = msgstr_string; *line != '\0'; )
803 if (strncmp (line, field, len) == 0 && line[len] == ':')
805 const char *p = line + len + 1;
807 /* Test whether the field's value, starting at p, is the default
811 if (default_values[cnt] != NULL
812 && strncmp (p, default_values[cnt],
813 strlen (default_values[cnt])) == 0)
815 p += strlen (default_values[cnt]);
816 if (*p == '\0' || *p == '\n')
819 xasprintf (_("header field '%s' still has the initial default value\n"),
821 po_xerror (severity, mp, NULL, 0, 0, true, msg);
823 if (severity == PO_SEVERITY_ERROR)
829 line = strchrnul (line, '\n');
836 xasprintf (_("header field '%s' missing in header\n"),
838 po_xerror (severity, mp, NULL, 0, 0, true, msg);
840 if (severity == PO_SEVERITY_ERROR)
848 /* Perform all checks on a non-obsolete message.
849 Return the number of errors that were seen. */
851 check_message (const message_ty *mp,
852 const lex_pos_ty *msgid_pos,
854 int check_format_strings,
855 const struct plural_distribution *distribution,
857 int check_compatibility,
858 int check_accelerators, char accelerator_char)
862 if (check_header && is_header (mp))
863 seen_errors += check_header_entry (mp, mp->msgstr);
865 seen_errors += check_pair (mp,
866 mp->msgid, msgid_pos, mp->msgid_plural,
867 mp->msgstr, mp->msgstr_len,
870 check_format_strings,
873 check_accelerators, accelerator_char);
878 /* Perform all checks on a message list.
879 Return the number of errors that were seen. */
881 check_message_list (message_list_ty *mlp,
882 int ignore_untranslated_messages,
883 int ignore_fuzzy_messages,
885 int check_format_strings,
887 int check_compatibility,
888 int check_accelerators, char accelerator_char)
891 struct plural_distribution distribution;
894 distribution.expr = NULL;
895 distribution.often = NULL;
896 distribution.often_length = 0;
897 distribution.histogram = NULL;
900 seen_errors += check_plural (mlp, ignore_untranslated_messages,
901 ignore_fuzzy_messages, &distribution);
903 for (j = 0; j < mlp->nitems; j++)
905 message_ty *mp = mlp->item[j];
908 && !(ignore_untranslated_messages && mp->msgstr[0] == '\0')
909 && !(ignore_fuzzy_messages && (mp->is_fuzzy && !is_header (mp))))
910 seen_errors += check_message (mp, &mp->pos,
912 check_format_strings,
914 check_header, check_compatibility,
915 check_accelerators, accelerator_char);
923 syntax_check_ellipsis_unicode (const message_ty *mp, const char *msgid)
925 const char *str = msgid;
926 const char *str_limit = str + strlen (msgid);
929 while (str < str_limit)
931 const char *end, *cp;
934 end = sentence_end (str, &ending_char);
936 /* sentence_end doesn't treat '...' specially. */
937 cp = end - (ending_char == '.' ? 2 : 3);
938 if (cp >= str && memcmp (cp, "...", 3) == 0)
940 po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false,
941 _("ASCII ellipsis ('...') instead of Unicode"));
953 syntax_check_space_ellipsis (const message_ty *mp, const char *msgid)
955 const char *str = msgid;
956 const char *str_limit = str + strlen (msgid);
959 while (str < str_limit)
961 const char *end, *ellipsis = NULL;
964 end = sentence_end (str, &ending_char);
966 if (ending_char == 0x2026)
968 else if (ending_char == '.')
970 /* sentence_end doesn't treat '...' specially. */
971 const char *cp = end - 2;
972 if (cp >= str && memcmp (cp, "...", 3) == 0)
977 /* Look for a '...'. */
978 const char *cp = end - 3;
979 if (cp >= str && memcmp (cp, "...", 3) == 0)
985 /* Look for a U+2026. */
986 for (cp = end - 1; cp >= str; cp--)
988 u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp);
1003 /* Look at the character before ellipsis. */
1004 for (cp = ellipsis - 1; cp >= str; cp--)
1006 u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp);
1011 if (uc != 0xfffd && uc_is_space (uc))
1013 po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false,
1015 space before ellipsis found in user visible strings"));
1029 const message_ty *mp;
1034 syntax_check_quote_unicode_callback (char quote, const char *quoted,
1035 size_t quoted_length, void *data)
1037 struct callback_arg *arg = data;
1042 po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false,
1043 _("ASCII double quote used instead of Unicode"));
1048 po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false,
1049 _("ASCII single quote used instead of Unicode"));
1059 syntax_check_quote_unicode (const message_ty *mp, const char *msgid)
1061 struct callback_arg arg;
1064 arg.seen_errors = 0;
1066 scan_quoted (msgid, strlen (msgid),
1067 syntax_check_quote_unicode_callback, &arg);
1069 return arg.seen_errors;
1073 typedef int (* syntax_check_function) (const message_ty *mp, const char *msgid);
1074 static const syntax_check_function sc_funcs[NSYNTAXCHECKS] =
1076 syntax_check_ellipsis_unicode,
1077 syntax_check_space_ellipsis,
1078 syntax_check_quote_unicode
1081 /* Perform all syntax checks on a non-obsolete message.
1082 Return the number of errors that were seen. */
1084 syntax_check_message (const message_ty *mp)
1086 int seen_errors = 0;
1089 for (i = 0; i < NSYNTAXCHECKS; i++)
1091 if (mp->do_syntax_check[i] == yes)
1093 seen_errors += sc_funcs[i] (mp, mp->msgid);
1094 if (mp->msgid_plural)
1095 seen_errors += sc_funcs[i] (mp, mp->msgid_plural);
1103 /* Perform all syntax checks on a message list.
1104 Return the number of errors that were seen. */
1106 syntax_check_message_list (message_list_ty *mlp)
1108 int seen_errors = 0;
1111 for (j = 0; j < mlp->nitems; j++)
1113 message_ty *mp = mlp->item[j];
1115 if (!is_header (mp))
1116 seen_errors += syntax_check_message (mp);